我有以下对象
[{
"key": "a1",
...
}, {
"key": "a2",
...
}, ...]
是否可以从该对象中提取联合类型"a1" | "a2" | ...
?
我知道可以通过使用TypeScript String Union to String Array中提供的元组API从['a1', 'a2', ...]
中提取它,但是我无法弄清楚它是否用于对象数组
答案 0 :(得分:4)
基本上,您只想对数组元素的"key"
属性进行lookup的操作,可以通过查找数组的number
属性来找到数组的元素。不幸的是,最困难的部分是使它显示为"string"
以外的任何内容。
const val = [{ key: "a1" }, { key: "a2" }]; // Array<{key: string}>
type ValueAtKey = (typeof val)[number]["key"]; // string
那是因为编译器推断val
只是具有string
值的对象数组。编译器使用一些启发式方法来确定when to widen literals,在上述情况下,确切的字符串文字已扩展为string
。
向编译器提示诸如"a1"
之类的值应缩小到"a1"
而不是扩大到string
的一种方法是使该值与类型{{3 }}到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;
literally()
函数仅返回其参数,但类型趋于更窄。是的,这很丑。
现在您可以这样做:
const val = literally([{ key: "a1" }, { key: "a2" }]); // Array<{key: "a1"}|{key: "a2"}>
type ValueAtKey = (typeof val)[number]["key"]; // "a1" | "a2"
val
对象在运行时是相同的,但是TypeScript编译器现在将其视为类型为{key: "a1"}
或{key: "a2"}
的值的数组。然后对ValueAtKey
完成的查找会为您提供您要查找的联合类型。
(请注意,我假设您不在这里val
的顺序。也就是说,您可以将其视为数组而不是constrained。因为联合类型{ {1}}没有固有的顺序,则该数组应该足够。)
希望有所帮助;祝你好运!