将字符串数组转换为打字稿中的对象键

时间:2021-06-11 17:46:53

标签: typescript

我有下一个数组

const arrayData = ['a', 'b'] as const;

这个数组有下一个类型 ArrayType = ('a' | 'b')[];

我想获取与下一个类型一致的对象:

type Type = {
  a: boolean,
  b: boolean,
}

预期对象

   const result : Type = {
     a: false,
     b: false,
   }

我想将 arrayData 转换为 result

const result: Type = arrayData.reduce((r, key) => {
  return {
    ...r,
    key: false,
  }
}, {});

但此代码没有有效类型

2 个答案:

答案 0 :(得分:1)

你的第一个假设是错误的:

const foo = ['a', 'b'] as const; // Type is ['a', 'b'], a tuple of literals
const bar = ['a', 'b'];          // Type is ('a' | 'b')[], a list of a union of literals

使用 ['a', 'b'] 而不管 const 您可以这样输入:

type ObjectFromList<T extends ReadonlyArray<string>, V = string> = {
  [K in (T extends ReadonlyArray<infer U> ? U : never)]: V
};

Full example on playground

说明:

  • T extends ReadonlyArray<string> 需要一个类型参数,它是一个数组,其元素可以变成字符串,只读允许您使用 const。每个字符串文字类型都可以传递到字符串中。
  • T extends ReadonlyArray<infer U> ? U : never 是一个条件,意思是:“如果 T 是一个数组,则获取其元素的类型(U),否则没有类型”。
    我们需要 T 来扩展一个数组,所以我们可以在 : 之后设置 never 意味着我们知道它永远不会发生。 infer U 将推断 T 可能的最小类型集,在您的情况下是字符串文字的并集 ('a' | 'b')
  • [K in ...]: V 使用数组元素中所有可能的值作为指向 V 类型值的键(我们将默认值设置为 string,但您可以传递另一个).

最后,关于reduce。您需要在迭代期间设置您正在使用的类型:

const result: Type = arrayData.reduce((r, key) => {
  return {
    ...r,
    [key]: false,
  }
}, {} as Type); // Here

要精确地限制类型,您需要通过键入初始累加器和函数的返回来键入reduce:

const result: Type = arrayData.reduce((r, key): Type /* HERE */ => {
  return {
    ...r,
    [key]: false,
  }
}, {} as Type);

Full example on playground

答案 1 :(得分:0)

我在您的示例中发现了 2 个问题:

  1. 对象的动态键应该在方括号内:(key: 应该是 [key]:

  2. 您可以在 TypeScript 中通过 reduce 运算符定义初始 as 累加器的类型。

const arrayData = ['a', 'b'] as const;

type Type = {
  a: boolean,
  b: boolean,
}

const result: Type = arrayData.reduce((r, key: string) => {
  return {
    ...r,
    [key]: false,
  }
}, {} as Type);