在此示例中,我希望表达式property
中的itemKV1
属性受到约束,因此当property
为age
时,value
只能是number
的类型。
关于如何做这样的事情的任何想法?
我知道如何使用函数中的泛型来执行此操作,因为它提供了here中所述的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
};
答案 0 :(得分:1)
通常不可能同时推断和约束变量的类型。您可以在注释中指定类型,也可以让编译器根据分配来推断类型。
但是对于您的特定情况,还有另一种解决方案来使您想要的分配出现错误。您可以生成所有可能的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
};
注意:itemKV1.value
仍将是string | number
类型,除非您根据property
字段将其缩小。如果希望变量的最终类型基于分配但受约束,则需要一个函数:
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
});