考虑以下示例:
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'
}
它甚至可能还是已经超出了打字稿的可能性?如果是这样,我想知道如何? :)
答案 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]
}
上试用