在这个例子中,我希望表达式itemKV1
中的property
属性约束自身,以便在property
age
时,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
});
游乐场链接