typescript - 如何从对象元组创建对象类型?

标签 typescript tuples mapped-types

从这个数据结构:

const properties = [
  { name: 'name', type: '' },
  { name: 'age', type: 0 },
  { name: 'sex', type: ['m', 'f'] as const },
  { name: 'username', type: '' }
]
我正在尝试动态构建以下类型:
type Person = {
  name: string;
  age: number;
  sex: 'm'|'f';
  username: string;
}
我知道 TypeScript 可以通过映射其他类型来创建类型。但是这里的源对象是一个数组,所以看起来有点棘手。我该怎么做?

最佳答案

映射类型确实是要走的路。为确保没有类型被加宽,您必须添加 as constproperties :

const properties = [
  { name: 'name', type: '' },
  { name: 'age', type: 0 },
  { name: 'sex', type: ['m', 'f'] as const },
  { name: 'username', type: '' }
] as const
然后,您可以使用映射类型,在该类型中将键从数组索引重新映射到属性名称并将值映射到类型。映射类型本身如下所示:
type FromProperties<P extends readonly unknown[]> = {
  [K in IndexKeys<P> as Name<P[K]>]: Type<P[K]>
} 
它映射实际索引的键( '0''1' 等)而不是数组属性,将键重新映射到属性 name ,并有 Type<P[K]>作为值(value)。
要获得正确的索引键,您可以排除 [] 上的属性。从你的数组中,所以只剩下索引:
type IndexKeys<A extends readonly unknown[]> = Exclude<keyof A, keyof []>
要获取名称,可以使用一个简单的条件类型:
type Name<O> = O extends { name: infer N } ? N extends string ? N : never : never
并确定每个type的实际类型值,您可以使用稍微复杂的条件类型:
type Type<O> = 
  O extends { type: infer T }
  ?   T extends number ? number 
    : T extends string ? string 
    : T extends readonly unknown[] ? T[number]
    : never // `name` property is not a number, string or array
  : never // object has no `type` property
extends 子句是为了防止推断太窄的类型(例如 '' 而不是 string )并推断数组的联合类型。如果需要,您可以添加更多类型。
有了这些定义,Properties可以用
type Person = FromProperties<typeof properties>
// Inferred type:
// type Person = {
//     name: string;
//     age: number;
//     sex: "m" | "f";
//     username: string;
// }
TypeScript playground

关于typescript - 如何从对象元组创建对象类型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66500731/

相关文章:

javascript - 无法创建 LookUpField

postgresql - Sequelize Include 在没有结果的情况下不起作用

typescript - 如何获取角度8中的元素引用名称

python - os.walk() 结果类型

python - 将范围元组列表折叠到重叠范围中

c# - 如何轻松初始化元组列表?

typescript - 从记录中排除键

typescript - 关于带有类型推断的映射元组类型的问题

reactjs - TypeScript React 谷歌地图 : 'google' does not exist

typescript - 映射类型 : removing optional modifier