Open jtwang7 opened 2 years ago
参考文章:
本文处理下面这个 TypeScript 开发场景: 有一个数组,数组中每一项都是一个对象,我希望定义一个 Type,是由数组中的每个对象中的某个属性值组成的联合类型 (union type)
// 数组 const configs = [ { name: 'width', value: '60px', }, { name: 'height', value: '40px', } ];
我期望将 configs 中的每一项中的 name 的实际字符串值,提炼成一个 union type。
// 期望得到的 type type ConfigName = 'width' | 'height';
最直接的做法是直接像上面一样手动定义一下。这样写的缺点是,如果 configs 中的元素又增加了,例如 name 的取值增加一个 'max-width' ,那我们需要更新 ConfigName 的的定义。无疑增加了维护成本。 使用 TypeScript 编程的原则之一:更少的类型维护,更安全的类型推断。
首先,我们尝试用 typeof 来进行类型定义。
type ConfigName = typeof configs[number]['name']; // 推断结果为 // type ConfigName = string; // 期望: // type ConfigName = "width" | "height";
这与我们实际期望不符,我们发现,被推断为了 string 类型。并不是我们期望的 union type
使用 TypeScriptconst 断言 const 断言有以下两个作用:
根据第 1 条规则,看上去好像可以恰好解决我们的问题,试一试:
// 对象断言为 const const configs = [ { name: 'width', value: '60px', }, { name: 'height', value: '40px', } ] as const; type ConfigName = typeof configs[number]['name']; // 推断为: // type ConfigName = "width" | "height"; // 期望: // type ConfigName = "width" | "height";
缺点:推断的属性会被赋予 readonly 不可变属性
readonly
在 TypeScript 中,我们想要描述两个值之间的对应关系时,会使用泛型。
type ConfigItem<T> = { name: T; value: string; }
function defineConfigs<T extends string>(configs: Array<ConfigItem<T>>) { return configs; } const configs = defineConfigs([ { name: 'width', value: '60px', }, { name: 'height', value: '40px', } ]); type ConfigName = typeof configs[number]['name']; // 推断为: // type ConfigName = "width" | "height"; // 期望: // type ConfigName = "width" | "height";
原理:我们使用泛型函数在函数的输入和输出之间创建了一个链接,当调用它时,会根据其输入的具体值,得到一个具体的类型。
至此,我们达到了最初的目的:
TypeScript 从数组元素的值中定义 Union Type
参考文章:
场景
本文处理下面这个 TypeScript 开发场景: 有一个数组,数组中每一项都是一个对象,我希望定义一个 Type,是由数组中的每个对象中的某个属性值组成的联合类型 (union type)
我期望将 configs 中的每一项中的 name 的实际字符串值,提炼成一个 union type。
解决思路
首先,我们尝试用 typeof 来进行类型定义。
这与我们实际期望不符,我们发现,被推断为了 string 类型。并不是我们期望的 union type
const 断言
使用 TypeScriptconst 断言 const 断言有以下两个作用:
根据第 1 条规则,看上去好像可以恰好解决我们的问题,试一试:
缺点:推断的属性会被赋予
readonly
不可变属性泛型函数 Generic Functions
在 TypeScript 中,我们想要描述两个值之间的对应关系时,会使用泛型。
原理:我们使用泛型函数在函数的输入和输出之间创建了一个链接,当调用它时,会根据其输入的具体值,得到一个具体的类型。
总结
至此,我们达到了最初的目的: