从对象数组中提取字符串并集

时间:2019-01-02 16:23:56

标签: typescript typescript-typings

我有以下对象

[{
    "key": "a1",
    ...
}, {
    "key": "a2",
    ...
}, ...]

是否可以从该对象中提取联合类型"a1" | "a2" | ...? 我知道可以通过使用TypeScript String Union to String Array中提供的元组API从['a1', 'a2', ...]中提取它,但是我无法弄清楚它是否用于对象数组

1 个答案:

答案 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}}没有固有的顺序,则该数组应该足够。)

希望有所帮助;祝你好运!