Как я могу задать тип массива, чтобы он был ключом интерфейса?

#typescript

Вопрос:

Мне довольно трудно это объяснить, так как я не знаю, как это назвать. У меня есть интерфейс, и я хочу задать некоторые свойства, используя элемент массива как таковой:

 interface MyStuff {  key?: boolean; };  var myThing: MyStuff = {};  var MyStuffArray: /* magic code */ = [];  MyStuffArray.push("key");  for(var p of MyStuffArray) {  myThing[p /* magic code */] = true; };  

магический код-это область, в которой я не знаю, как его использовать; потому что MyStuffArray может быть заполнен только ключами MyStuff .

Я пытался myThing[p as keyof MyStuff] = true; , но я получаю ошибку: Type 'boolean' is not assignable to type 'never'.

Это работает: (myThing as any)[p] = true , однако я чувствую, что это плохая практика, когда вам приходится использовать any ключевое слово в любой ситуации.

Если это поможет: я не хочу MyStuffArray , чтобы меня заполняли ключами от MyStuff ! Я просто хочу, чтобы MyStuffArray он был заполнен возможными ключами MyStuff .

Комментарии:

1. Разрешено ли массиву иметь несколько ключей одного и того же значения?

Ответ №1:

Вы можете использовать keyof оператор для объявления массива и проверить свойство перед выполнением назначения, как это:

 interface MyStuff {  key?: boolean;  other?: string; };  var myThing: MyStuff = {};  var MyStuffArray: (keyof MyStuff)[] = [];  MyStuffArray.push('key');  for (var p of MyStuffArray) {  if (p === 'key') {  myThing[p] = true;  } };  

Ответ №2:

Самый простой способ (и предпочтительный-просто использовать keyof ключевое слово, однако, если вы хотите добиться еще большей безопасности типов, вы можете продолжить со следующим кодом. Это не позволит вам дважды нажимать один и тот же ключ на массив.

 type UnionToIntersectionlt;Ugt; = (  U extends never ? never : (arg: U) =gt; never ) extends (arg: infer I) =gt; void  ? I  : never;  type UnionToTuplelt;Tgt; = UnionToIntersectionlt;  T extends never ? never : (t: T) =gt; T gt; extends (_: never) =gt; infer W  ? [...UnionToTuplelt;Excludelt;T, Wgt;gt;, W]  : [];  ////////////////////////// //////// your code ///////  interface MyStuff {  key?: boolean; };  var myThing: MyStuff = {};  // Only one element 'key' is possible in the array var myStuffArray: UnionToTuplelt;keyof MyStuffgt; = ['key'];  for(var p of myStuffArray) {  myThing[p /* magic code */] = true; };