首页 > 解决方案 > 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'
}

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

标签: typescript

解决方案


如果您的源结构实际上具有保存为文字的类型信息,您可以这样做。您可以通过使用const 断言来做到这一点

所以如果你这样做——

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'>

在操场上试一试。

应该注意的是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]
}

在操场上试试


推荐阅读