请考虑以下事项:
type ValueMap = {
foo: 'FOO1' | 'FOO2';
bar: 'BAR1' | 'BAR2' | 'BAR3';
};
type Key = keyof ValueMap;
type Value<K extends Key> = ValueMap[K];
type Entry<K extends Key> = {
key: K;
value: Value<K>;
}
换句话说,Entry
由key
和value
组成,允许的值集取决于密钥,因此例如
{key: 'foo', value: 'FOO2'} - valid
{key: 'foo', value: 'BAR3'} - invalid
{key: 'bar', value: 'BAR1'} - valid
{key: 'bar', value: 'FOO2'} - invalid
现在,我想要将一组这样的条目发送到一个函数,并且希望从that element's key推断出每个条目的类型.但是,如果我以数组的形式执行此操作,则不能很好地工作:
function sendArray<K extends Key>(v: Array<Entry<K>>) {
...
}
sendArray([{key: 'foo', value: 'FOO2'}, {key: 'bar', value: 'BAR1'}])
sendArray([{key: 'foo', value: 'FOO2'}, {key: 'bar', value: 'FOO1'}]) // compiles :(
这里,sendArray
被调用,K
被推断为"foo" | "bar"
,并且每个数组元素仅被验证,使得key
可被赋值给"foo" | "bar"
,value
可被赋值给ValueMap<"foo" | "bar">
,即来自foo
的值对于bar
个条目是有效的,反之亦然.:(
我知道,如果我改用记录类型,它会起作用:
type Entries<K extends Key> = {
[P in K]?: Value<P>;
}
function sendRecord<K extends Key>(v: EntryRecord<K>) {
}
sendRecord({foo: 'FOO2', bar: 'BAR3'})
sendRecord({foo: 'FOO2', bar: 'FOO1'}) // does not compile! :)
...这很好,但我真的希望这对数组起作用.有没有办法这样做,从而推断出第一个数组元素是Entry<"foo">
,而第二个元素是Entry<"bar">
?