我想声明一个类型强制的项数组,并能够从中派生联合类型。如果您未为数组中的项目显式指定类型,则此模式有效。我不确定如何最好地解释它,所以这里有一个例子:
示例1
type Pair = {
key: string;
value: number;
};
const pairs: ReadonlyArray<Pair> = [
{ key: 'foo', value: 1 },
{ key: 'bar', value: 2 },
] as const;
type Keys = typeof pairs[number]['key']
示例2
type Data = {
name: string;
age: number;
};
const DataRecord: Record<string, Data> = {
foo: { name: 'Mark', age: 35 },
bar: { name: 'Jeff', age: 56 },
} as const;
type Keys = keyof typeof DataRecord;
以下是使用as const
时派生密钥的示例。我想要这种行为,但是要显式键入数组。
const pairs = [
{ key: 'foo', value: 1 },
{ key: 'bar', value: 2 },
] as const;
type Keys = typeof pairs[number]['key']; // "foo" | "bar"
键的期望值:"foo"|"bar"
键的实际值:string
答案 0 :(得分:5)
对于变量,您可以让编译器从初始化中推断类型,也可以明确地将其写出。如果像您一样显式地编写它,则将根据注释检查初始化值,但是初始化器的实际类型不会影响变量的类型(因此会丢失所需的类型信息)。如果让编译器进行推断,就不再可能限制类型以符合特定接口(如您所愿)
解决方案是使用泛型函数来约束值并推断其实际类型:
type Pair = {
key: string;
value: number;
};
function craetePairsArray<T extends readonly Pair[] & Array<{key: V}>, V extends string>(...args: T) {
return args
}
const pairs = craetePairsArray(
{ key: 'foo', value: 1 },
{ key: 'bar', value: 2 },
)
type Keys1 = typeof pairs[number]['key']
type Data = {
name: string;
age: number;
};
function craeteDataObject<T extends Record<string, Data>>(arg: T) {
return arg;
}
const DataRecord = craeteDataObject({
foo: { name: 'Mark', age: 35 },
bar: { name: 'Jeff', age: 56 },
})
type Keys2 = keyof typeof DataRecord;
注意:对于数组的情况,我们需要让编译器有力地为key
推断字符串文字类型,从而推断整个& Array<{key: V}>
,其中V
是类型参数的扩展string
答案 1 :(得分:3)
通常的方法是:
pairs
来推断ReadonlyArray<Pair>
的类型(请参阅answer)key
中的Pair
类型"foo"|"bar"
如果您不想想要这样做,那么推断您的键和限制pairs
类型的唯一方法是使用助手功能。 Pair
类型也将成为通用类型,以保存给定的key
字符串文字类型。您可以使用IIFE使任务紧凑:
type Pair<K = string> = {
key: K;
value: number;
};
const pairs = (<T>(p: readonly Pair<T>[]) => p)([
{ key: 'foo', value: 1 },
{ key: 'bar', value: 2 },
] as const) // readonly Pair<"foo" | "bar">[]
type Keys = typeof pairs[number]['key'] // "foo" | "bar"