想要从第一个参数为第二个参数创建过滤类型
请检查以下代码:
interface TypeWithLabel {
label: string;
list: string;
}
interface A extends TypeWithLabel{
label: 'a';
list: '1' | '2' | '3';
}
interface B extends TypeWithLabel {
label: 'b';
list: '4' | '5' | '6';
}
type TypeProperty<T, U extends keyof T> = T[U];
function ab<T extends TypeWithLabel, U = TypeProperty<T, 'label'>>(
label: U,
item: TypeProperty<T, 'list'>
) {
}
// want to get A Only with label:'a'
// then display '1' | '2' | '3' for item
ab<A | B>('a', '1'); // correct
ab<A | B>('a', '4'); // error
// want to get B Only with label:'b'
// then display '4' | '5' | '6' for item
ab<A | B>('b', '4'); // correct
ab<A | B>('b', '1'); // error
也许,有没有另一种过滤接口的方法? 我想过如何重用泛型,但label
函数中需要字符串值。
不确定,如果我理解正确 - 如果您希望函数ab
的作用域为A
或B
,那么您的泛型类型参数也应该反映此要求。您需要将代码更改为:
// given A, restrict item to '1' | '2' | '3'
ab<A>("a", "1"); // ok
ab<A>("a", "4"); // error (ok)
// given A, restrict item to '4' | '5' | '6'
ab<B>("b", "4"); // ok
ab<B>("b", "1"); // error (ok)
操场
上面的代码有一个轻微的缺点,即必须手动设置泛型类型参数。如果有一天U = TypeProperty<T, 'label'>
无法再提供默认类型,则必须在每个涉及ab
的代码位置添加U
,并且无法推断。
另一种方法是创建查找类型LabelToList
。如果您只有几个接口(如A
和B
(以及许多ab
调用,则这种风格是有利的。可以通过对示例进行如下编码来省略手动泛型类型参数:
type LabelToList = {
a: A;
b: B;
};
function ab<K extends keyof LabelToList>(
label: K,
item: LabelToList[K]["list"]
) {}
操场