接口和不带函数的类型的类型参数推断



在这个例子中,我希望表达式itemKV1中的property属性约束自身,以便在propertyage时,value只能是一种number

关于如何做这样的事情的任何想法?

我知道如何使用函数中的泛型来做到这一点,因为它提供了type argument inference,如此处所述。

问题是我无法推断property来约束value.我想不出用接口或类型来做到这一点的方法。

interface Item {
id: string;
name: string;
age: number;
}
// Where can I add a generic for `keyof T`?
type KV<T> = { property: keyof T; value: T[keyof T] };
// I want value to be of type `number`, not `string | number`
// this should show an error, but doesn't.
const itemKV1: KV<Item> = {
property: "age",
value: "not a number!"
};
// This should not error and doesn't.
const itemKV2: KV<Item> = {
property: "age",
value: 82
};

通常不可能同时推断和约束变量的类型。您可以在批注中指定类型,也可以让编译器根据赋值推断类型。

但是,对于您的特定情况,还有另一种解决方案可以在您想要的作业上出错。您可以将所有可能的property/value组合的并集生成为联合。

interface Item {
id: string;
name: string;
age: number;
}
// Where can I add a generic for `keyof T`?
type KV<T> = {
[P in keyof T]: { property: P; value: T[P] };
}[keyof T]
// KV<Item> =  
//   | { property: "id"; value: string; }
//   | { property: "name"; value: string; }
//   | { property: "age"; value: number; }
// Error value is not numebr 
const itemKV1: KV<Item> = {
property: "age",
value: "not a number!"
};
// ok
const itemKV2: KV<Item> = {
property: "age",
value: 82
};

游乐场链接

注意:除非您根据property字段缩小范围,否则itemKV1.value仍将属于string | number类型。如果您希望变量的最终类型基于赋值但受约束,则需要一个函数:

function property<T>() {
return function <TKV extends KV<T>>(o: TKV) {
return o 
}
}
// ok
// const itemKV2: {
//     property: "age";
//     value: number;
// }
const itemKV2 = property<Item>()({
property: "age",
value: 82
});

游乐场链接

最新更新