打字稿从数据推断文字

时间:2021-04-26 17:43:25

标签: typescript

考虑以下示例:

type ArrayMember<T> = T extends Array<infer Member> ? Member : T;

const data = [
    {
        key: 1,
        value: 'some value'
    },
    {
        key: 2,
        value: 'another value'
    }
]

type ResultType = ArrayMember<typeof data>

// Inferred type "ResultType" is:
// type ResultType = {
//     key: number;
//     value: string;
// }

我正在寻找如何获得这样的结果:

type ResultType = {
    key: 1 | 2;
    value: 'some value' | 'another value'
}

它甚至可能还是已经超出了打字稿的可能性?如果是这样,我想知道如何? :)

1 个答案:

答案 0 :(得分:1)

如果您的源结构实际上具有保存为文字的类型信息,您就可以这样做。您可以使用 const assertions

所以如果你这样做-

const data = [
    {
        key: 1,
        value: 'some value'
    },
    {
        key: 2,
        value: 'another value'
    }
] as const;

您会注意到 typeof data 看起来像-

type DataType = readonly [{
    readonly key: 1;
    readonly value: "some value";
}, {
    readonly key: 2;
    readonly value: "another value";
}]

类型信息保留在文字级别。现在您可以使用-

获取key的类型
type DataType = typeof data;
type Foo = DataType[number]['key'];
// ^ The type is 1 | 2 

知道了这一切,你就可以通过做——来达到你想要的结果

type DataType = typeof data;
type ResultType = Pick<DataType[number], 'key' | 'value'>

playground 上试用。

需要注意的是,在整个数组上应用 as const 会使每个属性readonly

如果您不希望那样,您可以将 as const 一一应用于每个属性值,或者只是使用映射类型和 -readonly 限定符来摆脱它们-

type DataType = typeof data;
type ReadonlyResultType = Pick<DataType[number], 'key' | 'value'>;
type ResultType = {
  -readonly [K in keyof ReadonlyResultType]: ReadonlyResultType[K]
}

playground

上试用