从数组到对象的TypeScript类型

米哈尔

我有数组,其中每个项目都是array [name: string, someFunction: Function]我想将其转换为键为names且值为someFunctions的对象:

// Input
const arrayFunctions = [
    ['getLength', (text: string) => text.length],
    ['setValue', (id: string, value: number) => {}],
    ['getAll', () => ([1, 2, 3])]
]

// Output
const objectFunctions = {
    getLength: (text: string) => text.length,
    setValue: (id: string, value: number) => {},
    getAll: () => ([1, 2, 3])
}

有什么方法可以连接输入数组中的函数类型和输出对象中的函数类型?

type ObjectFunctions<ArrayFunctions> = { [/* Value from ArrayFunctions[i][0] */]: /* Value from ArrayFunctions[i][1] */ }

const arrayToObject = <ArrayFunctions extends Array<any>>(functions: ArrayFunctions) => {
    const result = {}

    for (const [name, func] of functions) {
        result[name] = func
    }

    return result as ObjectFunctions<ArrayFunctions>
}

const arrayFunctions = [
    ['getLength', (text: string) => text.length],
    ['setValue', (id: string, value: number) => {}],
    ['getAll', () => ([1, 2, 3])]
]

const objectFunctions = arrayToObject(arrayFunctions)

const length = objectFunctions.getLength() // Should be error because first parameter (text) is missing.
objectFunctions.setValue(true, 2) // Should be error, because of first parameter (id) must be string.
Aleksey L.

如果数组是在编译时定义的,则打字稿将有机会推断类型。

将内部元组转换为object

type ToObject<T> = T extends readonly [infer Key, infer Func]
  ? Key extends PropertyKey
  ? { [P in Key]: Func } : never : never;

这将使我们可以转换['getLength', (text: string) => text.length]
{ getLength: (text: string) => number }

将元组数组转换为对象数组array上的映射类型):

type ToObjectsArray<T> = {
  [I in keyof T]: ToObject<T[I]>
};

这将使我们能够将数组数组转换为对象数组。
现在,我们可以通过查询数组项的类型来 提取所需对象的并集Array[number]

最后一步-我们实际上需要交集而不是联合。我们可以使用著名的UnionToIntersection

type UnionToIntersection<U> =
  (U extends any ? (k: U) => void : never) extends ((k: infer I) => void) ? I : never;

结合在一起

// @ts-ignore
type FunctionMap<ArrayFunctions> = UnionToIntersection<ToObjectsArray<ArrayFunctions>[number]>;

忽略上面需要的内容,因为打字稿会忘记在数组类型上使用映射类型时会生成数组。


好,让我们测试一下:

const arrayToObject = <ArrayFunctions extends ReadonlyArray<any>>(functions: ArrayFunctions) => {
  const result: any = {}

  for (const [name, func] of functions) {
    result[name] = func
  }

  return result as FunctionMap<ArrayFunctions>
}

const arrayFunctions = [
  ['getLength', (text: string) => text.length],
  ['setValue', (id: string, value: number) => { }],
  ['getAll', () => ([1, 2, 3])]
] as const;

const objectFunctions = arrayToObject(arrayFunctions);

const l = objectFunctions.getLength() // Expected 1 arguments, but got 0
objectFunctions.setValue(true, 2) // Argument of type 'true' is not assignable to parameter of type 'string'.

操场

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

Typescript:对象类型到数组类型(元组)

TypeScript:元组类型到对象类型

Typescript对象类型转换为数组类型

Angular / Typescript找不到类型为“对象”的其他支持对象“ [对象对象]”。NgFor仅支持绑定到数组等Iterables

Typescript中对象到对象数组的转换

如何从 TypeScript 中的对象数组创建类型?

包含对象的 TypeScript 类型化数组

Typescript-从联合或数组派生对象类型

Typescript数组对象属性值作为类型

Typescript 通用如何使 typeof 对象到数组?

根据Typescript中的对象数组创建对象类型

TypeScript - 合并到单个对象数组的数组的强类型化

获取特定类型的对象数组到新数组

Angular 5 + Typescript - 返回新创建的类型对象数组

Typescript,定义对象,它是数组中所有类型的乘积

TypeScript:用于通过reduce传递对象数组的正确类型

TypeScript:对对象数组进行排序时出现类型错误

React组件的TypeScript类型prop是对象数组吗?

TypeScript中带有对象的数组的类型定义

匹配任何对象但不匹配数组的TypeScript类型

数组到对象数组

数据集到Javascript / Typescript中的对象数组

TypeScript 类型“对象”与对象接口,为什么没有“数组”类型?

Typescript递归映射对象属性类型:对象和数组元素类型

如何使用TypeScript将对象类型数组转换为平面对象类型?

对象的对象到对象的数组

类型为“对象”的角度8错误“ [[对象对象]”)。NgFor仅支持绑定到数组等Iterables

Typescript对象属性类型

TypeScript对象类型