Nat*_*ia 5 typescript typescript-typings
我有以下对象
[{
"key": "a1",
...
}, {
"key": "a2",
...
}, ...]
Run Code Online (Sandbox Code Playgroud)
是否可以"a1" | "a2" | ...从此对象中提取联合类型?我知道可以['a1', 'a2', ...]通过使用元组 API来提取它,这里介绍了TypeScript String Union to String Array,但我无法弄清楚对象数组
基本上,您只想查找"key"数组元素的属性,通过查找其number属性可以找到数组的元素。不幸的是,困难的部分是让它显示为除"string".
const val = [{ key: "a1" }, { key: "a2" }]; // Array<{key: string}>
type ValueAtKey = (typeof val)[number]["key"]; // string
Run Code Online (Sandbox Code Playgroud)
那是因为编译器推断val只是一个带有string值的对象数组。编译器使用一些启发式方法来确定何时扩大文字,在上述情况下,确切的字符串文字已扩大到string。
TS3.4+ 更新
从 TypeScript 3.4 开始,让编译器推断对象/数组文字的最具体类型的推荐方法是使用const断言:
const val = [{ key: "a1" }, { key: "a2" }] as const;
// const val: readonly [{ readonly key: "a1"; }, { readonly key: "a2"; }]
type ValueAtKey = (typeof val)[number]["key"]; // "a1" | "a2"
Run Code Online (Sandbox Code Playgroud)
原 TS3.4 之前的答案
在 TS3.4 之前,您必须做其他事情。向编译器提示像这样的值"a1"应该缩小到"a1"而不是扩大到的方法之一string是让值匹配约束到的类型string(或包含它的联合)。以下是我有时用来执行此操作的辅助函数:
type Narrowable =
string | number | boolean | symbol | object |
null | undefined | void | ((...args: any[]) => any) | {};
const literally = <T extends { [k: string]: V | T } | Array<{ [k: string]: V | T }>,
V extends Narrowable>(t: T) => t;
Run Code Online (Sandbox Code Playgroud)
该literally()函数仅返回其参数,但类型往往更窄。是的,它很丑。
现在你可以这样做:
const val = literally([{ key: "a1" }, { key: "a2" }]); // Array<{key: "a1"}|{key: "a2"}>
type ValueAtKey = (typeof val)[number]["key"]; // "a1" | "a2"
Run Code Online (Sandbox Code Playgroud)
该val对象在运行时是相同的,但 TypeScript 编译器现在将其视为类型为{key: "a1"}或的值的数组{key: "a2"}。然后完成的查找为ValueAtKey您提供您正在寻找的联合类型。
(请注意,我假设您不关心val此处的排序。也就是说,您可以将其视为数组而不是元组。由于联合类型"a1" | "a2"没有固有的排序,因此数组应该是充足的。)
| 归档时间: |
|
| 查看次数: |
410 次 |
| 最近记录: |