কোনও টাইপসক্রিপ্ট অবজেক্টের ইনডেক্সড সদস্যদের প্রকার প্রয়োগ করে?


289

আমি টাইপসক্রিপ্ট অবজেক্টে স্ট্রিং -> স্ট্রিংয়ের একটি ম্যাপিং সংরক্ষণ করতে চাই এবং এটি প্রয়োগ করে সমস্ত কী কী স্ট্রিংয়ে ম্যাপ করে। উদাহরণ স্বরূপ:

var stuff = {};
stuff["a"] = "foo";   // okay
stuff["b"] = "bar";   // okay
stuff["c"] = false;   // ERROR!  bool != string

আমার জন্য কি প্রয়োগ করার কোনও উপায় আছে যে মানগুলি অবশ্যই স্ট্রিং (বা যাই হোক না কেন ..)?

উত্তর:


521
var stuff: { [key: string]: string; } = {};
stuff['a'] = ''; // ok
stuff['a'] = 4;  // error

// ... or, if you're using this a lot and don't want to type so much ...
interface StringMap { [key: string]: string; }
var stuff2: StringMap = { };
// same as above

13
এই বাক্য গঠনটি সম্পর্কে আকর্ষণীয় বিষয়টি হ'ল কীটির জন্য 'স্ট্রিং' ব্যতীত অন্য কোনও ধরণ আসলে ভুল। জেএস মানচিত্রগুলি স্ট্রিং দ্বারা সুস্পষ্টভাবে কীড করা হলেও নিখুঁত ধারণা তৈরি করে, তবে এটি সিনট্যাক্সটিকে কিছুটা অপ্রয়োজনীয় করে তোলে। মানগুলির ধরণগুলি নির্দিষ্ট করার জন্য 'specify}: স্ট্রিং' এর মতো কিছু সহজ মনে হয়, যদি না তারা উত্পন্ন কোডের অংশ হিসাবে কীগুলির স্বয়ংক্রিয় জবরদস্তির অনুমতি দেওয়ার জন্য কোনও উপায়ে যোগ না করে।
আর্মেন্টেজ

42
numberইনডেক্সিং টাইপ হিসাবেও অনুমোদিত
রায়ান কাভানহো

3
লক্ষণীয় মূল্য: সংকলকটি মূল প্রকারটি নয়, কেবলমাত্র মান প্রকারটি প্রয়োগ করে। আপনি স্টাফ করতে পারেন [15] = 'যাই হোক না কেন' এবং এটি অভিযোগ করবে না।
অ্যামুইনটার

3
না, এটি মূল ধরণের প্রয়োগ করে। আপনি স্টাফ করতে পারবেন না [myObject] = 'যাই হোক না কেন' এমনকি মাইওবজেক্টে একটি দুর্দান্ত ট্যাস্ট্রিং () বাস্তবায়ন রয়েছে।
আলেক্সজি

7
@ রায়ানকাভানফ কি type Keys = 'Acceptable' | 'String' | 'Keys'কোনও সূচক (কী) টাইপ হিসাবে ব্যবহার করা সম্ভব (বা এটি হবে) ?
কালেবয়ড

130
interface AgeMap {
    [name: string]: number
}

const friendsAges: AgeMap = {
    "Sandy": 34,
    "Joe": 28,
    "Sarah": 30,
    "Michelle": "fifty", // ERROR! Type 'string' is not assignable to type 'number'.
};

এখানে, ইন্টারফেসটি AgeMapস্ট্রিং হিসাবে কীগুলি এবং সংখ্যা হিসাবে মান প্রয়োগ করে। শব্দ nameকোনো শনাক্তকারী হতে পারে এবং আপনার ইন্টারফেস / টাইপ সিনট্যাক্স সুপারিশ ব্যবহার করা উচিত।

আপনি ইউনিয়ন প্রকারে প্রতিটি প্রবেশের জন্য একটি অবজেক্টের কী রয়েছে তা প্রয়োগ করতে আপনি অনুরূপ সিনট্যাক্স ব্যবহার করতে পারেন:

type DayOfTheWeek = "sunday" | "monday" | "tuesday" | "wednesday" | "thursday" | "friday" | "saturday";

type ChoresMap = { [day in DayOfTheWeek]: string };

const chores: ChoresMap = { // ERROR! Property 'saturday' is missing in type '...'
    "sunday": "do the dishes",
    "monday": "walk the dog",
    "tuesday": "water the plants",
    "wednesday": "take out the trash",
    "thursday": "clean your room",
    "friday": "mow the lawn",
};

আপনি অবশ্যই এটি একটি জেনেরিক টাইপও করতে পারেন!

type DayOfTheWeek = "sunday" | "monday" | "tuesday" | "wednesday" | "thursday" | "friday" | "saturday";

type DayOfTheWeekMap<T> = { [day in DayOfTheWeek]: T };

const chores: DayOfTheWeekMap<string> = {
    "sunday": "do the dishes",
    "monday": "walk the dog",
    "tuesday": "water the plants",
    "wednesday": "take out the trash",
    "thursday": "clean your room",
    "friday": "mow the lawn",
    "saturday": "relax",
};

const workDays: DayOfTheWeekMap<boolean> = {
    "sunday": false,
    "monday": true,
    "tuesday": true,
    "wednesday": true,
    "thursday": true,
    "friday": true,
    "saturday": false,
};

10.10.2018 আপডেট: নীচে @ ড্র্যাকস্ট্যাক্সির উত্তরটি দেখুন - এখন একটি বিল্ট-ইন টাইপ রয়েছে Recordযা আপনার পক্ষে বেশিরভাগ ক্ষেত্রে এটি করে।

1.2.2020 আপডেট: আমি আমার উত্তর থেকে প্রাক-তৈরি ম্যাপিং ইন্টারফেসগুলি পুরোপুরি সরিয়েছি। @ ড্র্যাকস্ট্যাক্সির উত্তর এগুলিকে সম্পূর্ণ অপ্রাসঙ্গিক করে তুলেছে। আপনি যদি এখনও সেগুলি ব্যবহার করতে চান তবে সম্পাদনার ইতিহাস পরীক্ষা করুন।


1
{[কী: সংখ্যা]: টি; types টাইপসেফ নয় কারণ অভ্যন্তরীণভাবে কোনও সামগ্রীর কীগুলি সর্বদা একটি স্ট্রিং থাকে - আরও তথ্যের জন্য @tep দ্বারা প্রশ্নের মন্তব্য দেখুন। উদাহরণস্বরূপ x = {}; x[1] = 2;Chrome এ চালানো পরে Object.keys(x)["1"] JSON.stringify(x)ফেরত দেয় এবং '1 "1": 2।' ফেরত দেয়। Numberটাইপফের সাথে কর্নার কেসগুলি (যেমন ইনফিনিটি, এনএএন, 1e300, 999999999999999999999 ইত্যাদি) স্ট্রিং কীগুলিতে রূপান্তরিত হয়। পছন্দ স্ট্রিং কী এর জন্য অন্যান্য কোণ ক্ষেত্রে হুঁশিয়ার x[''] = 'empty string';, x['000'] = 'threezeros'; x[undefined] = 'foo'
রোবোক্যাট

@robocat এটি সত্য, এবং আমি এই উত্তরটি থেকে কিছু সময়ের জন্য নম্বর কীড ইন্টারফেসগুলি সরিয়ে সম্পাদনা করতে পিছনে পিছনে গিয়েছি। অবশেষে আমি এগুলি টাইপসক্রিপ্ট প্রযুক্তিগতভাবে রাখার সিদ্ধান্ত নিয়েছি এবং সুনির্দিষ্টভাবে সংখ্যা-হিসাবে-কীগুলি মঞ্জুর করে । এটি বলার পরে, আমি আশা করি যে সংখ্যার সাথে সূচকযুক্ত বস্তুগুলি ব্যবহারের সিদ্ধান্ত নেওয়ার কেউ আপনার মন্তব্যটি দেখে।
স্যান্ডি গিফোর্ড

75

একটি দ্রুত আপডেট: টাইপস্ক্রিপ্ট ২.১ থেকে একটি বিল্ট টাইপ রয়েছে Record<T, K>যা অভিধানের মতো কাজ করে।

দস্তাবেজের একটি উদাহরণ:

// For every properties K of type T, transform it to U
function mapObject<K extends string, T, U>(obj: Record<K, T>, f: (x: T) => U): Record<K, U>

const names = { foo: "hello", bar: "world", baz: "bye" };
const lengths = mapObject(names, s => s.length);  // { foo: number, bar: number, baz: number }

টাইপস্ক্রিপ্ট ২.১ ডকুমেন্টেশন চালু আছে Record<T, K>

এই ওভারটি ব্যবহার করার জন্য আমি কেবলমাত্র অসুবিধেটি দেখতে পাচ্ছি {[key: T]: K}হ'ল আপনি "কী" এর জায়গায় কী কী ব্যবহার করছেন তা দরকারী তথ্য এনকোড করতে পারেন উদাহরণস্বরূপ যদি আপনার অবজেক্টের কেবল প্রাইম কী থাকে তবে আপনি এটির মতো ইঙ্গিত করতে পারতেন:{[prime: number]: yourType}

এই রূপান্তরগুলিতে সহায়তা করার জন্য আমি লিখেছিলাম একটি রেইজেক্স। এটি কেবলমাত্র কেসগুলিতে রূপান্তর করবে যেখানে লেবেলটি "কী"। অন্যান্য লেবেলগুলিকে রূপান্তর করতে কেবল প্রথম ক্যাপচারিং গ্রুপটি পরিবর্তন করুন:

অনুসন্ধান: \{\s*\[(key)\s*(+\s*:\s*(\w+)\s*\]\s*:\s*([^\}]+?)\s*;?\s*\}

প্রতিস্থাপন করুন: Record<$2, $3>


3
এটি আরও উন্নত হওয়া উচিত - এটি মূলত আমার উত্তরটির নতুন, নেটিভ সংস্করণ।
স্যান্ডি গিফোর্ড

রেকর্ড একটি মধ্যে সংকলন না {}?
ডগলাস গ্যাসকেল

সংযুক্ত কোডে @ ডগলাসগ্যাসেল প্রকারের কোনও উপস্থিতি নেই। Recordগুলি (জাভাস্ক্রিপ্ট Mapএর বিপরীতে, বলুন ) কেবল কোনও অবজেক্টের লিখিত সামগ্রীকে প্রয়োগ করার একটি উপায় সরবরাহ করে। আপনি করতে new Record...এবং const blah: Record<string, string>;সংকলন করতে পারবেন না const blah;
স্যান্ডি গিফোর্ড

এই উত্তরটি আমাকে কতটা সহায়তা করেছে তা আপনি কল্পনাও করতে পারবেন না, আপনাকে অনেক অনেক ধন্যবাদ :)
ফেডেরিকো গ্র্যান্ডি

উল্লেখযোগ্য যে স্ট্রিং ইউনিয়নগুলিও কাজ করে Record: const isBroken: Record<"hat" | "teapot" | "cup", boolean> = { hat: false, cup: false, teapot: true };
স্যান্ডি গিফোর্ড

10

@ রায়ান ক্যাভানফের উত্তর সম্পূর্ণ ঠিক এবং এখনও বৈধ। তবুও ফাল'১16 হিসাবে এটি যুক্ত করা উচিত যখন আমরা দাবি করতে পারি যে ES6 বেশিরভাগ প্ল্যাটফর্মের দ্বারা সমর্থিত এটি যখনই আপনাকে কোনও কী এর সাথে কিছু ডেটা সংযুক্ত করার দরকার হয় তখন মানচিত্রে লেগে থাকা প্রায় সবসময়ই ভাল।

যখন আমরা লিখি let a: { [s: string]: string; }আমাদের মনে রাখতে হবে যে টাইপসক্রিপটি সংকলনের পরে টাইপ ডেটার মতো কোনও জিনিস নেই, এটি কেবল সংকলনের জন্য ব্যবহৃত হয়। এবং {[গুলি: স্ট্রিং]: স্ট্রিং; just কেবল {to তে সংকলন করবে}

এটি বলেছিল, এমনকি আপনি যদি কিছু লিখেন তবে:

class TrickyKey  {}

let dict: {[key:TrickyKey]: string} = {}

এটি কেবল সংকলন করবে না (এমনকি এর জন্যও target es6আপনি পাবেন)error TS1023: An index signature parameter type must be 'string' or 'number'.

সুতরাং কার্যত আপনি সম্ভাব্য কী হিসাবে স্ট্রিং বা সংখ্যার সাথে সীমাবদ্ধ রয়েছেন তাই এখানে চেক প্রয়োগ করার ধরণের ধারণাটি তেমন নেই, বিশেষত মনে রাখবেন যে যখন জেএস সংখ্যা দ্বারা কী অ্যাক্সেস করার চেষ্টা করে এটি স্ট্রিংতে রূপান্তরিত করে।

সুতরাং এটি ধরে রাখা বেশ নিরাপদ যে সর্বোত্তম অনুশীলন হ'ল কীগুলি স্ট্রিং থাকলেও মানচিত্রটি ব্যবহার করা হয়, সুতরাং আমি এটির সাথে থাকি:

let staff: Map<string, string> = new Map();

4
এই উত্তরটি পোস্ট করার সময় এটি সম্ভব হয়েছিল কিনা তা নিশ্চিত নন তবে আজ আপনি এটি করতে পারেন: let dict: {[key in TrickyKey]: string} = {}- TrickyKeyস্ট্রিং আক্ষরিক প্রকারটি (যেমন "Foo" | "Bar")।
রোমান স্টারকভ

ব্যক্তিগতভাবে আমি দেশীয় টাইপস্ক্রিপ্ট ফর্ম্যাটটি পছন্দ করি তবে আপনি মানটি ব্যবহার করা সবচেয়ে ভাল। এটি আমাকে "নাম" কীটি নথিভুক্ত করার একটি উপায় দেয় যা সত্যই ব্যবহারযোগ্য নয় তবে আমি কীটিকে "রোগীআইডি" জাতীয় কিছু বলে তৈরি করতে পারি :)
কোডিং

এই উত্তরটি একেবারে বৈধ, এবং খুব ভাল পয়েন্ট তৈরি করে, তবে আমি এই ধারণাটির সাথে একমত নই যে দেশীয় Mapঅবজেক্টগুলিতে লেগে থাকা প্রায় সর্বদা ভাল । মানচিত্র অতিরিক্ত মেমরির ওভারহেড নিয়ে আসে এবং (আরও গুরুত্বপূর্ণভাবে) জেএসএন স্ট্রিং হিসাবে সঞ্চিত কোনও ডেটা থেকে ম্যানুয়ালি ইনস্ট্যান্ট করা দরকার। এগুলি প্রায়শই খুব দরকারী, তবে এগুলির মধ্যে ধরণের প্রকার পাওয়ার জন্য কেবল তা নয়।
স্যান্ডি গিফোর্ড

7

ইন্টারফেস সংজ্ঞায়িত করুন

interface Settings {
  lang: 'en' | 'da';
  welcome: boolean;
}

সেটিংস ইন্টারফেসের একটি নির্দিষ্ট কী হতে কী প্রয়োগ করুন

private setSettings(key: keyof Settings, value: any) {
   // Update settings key
}

3

@ শাবঙ্কের উত্তরে বিল্ডিংয়ের ফলে, কী বা মান - বা উভয়ই - আপনি প্রয়োগ করতে চান এমন কিছু হতে পারে allow

type IdentifierKeys = 'my.valid.key.1' | 'my.valid.key.2';
type IdentifierValues = 'my.valid.value.1' | 'my.valid.value.2';

let stuff = new Map<IdentifierKeys, IdentifierValues>();

সংজ্ঞা enumপরিবর্তে ব্যবহার করেও কাজ করা উচিত type

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.