与类型不匹配的打字脚本泛型键 [英] Typescript generics keyof doesn't match type
本文介绍了与类型不匹配的打字脚本泛型键的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!
问题描述
我有这个接口,它只存储另一个接口的键(modelKey
)和该键的值(value
):
interface ValueHolder<T, H extends keyof T> {
modelKey: H;
value: T[H];
}
现在我想存储以下模型中的horsePower
,匹配的类型位于ValueHolder
中:
interface Car {
id: number;
horsePower?: number;
date: Date;
};
如下所示:
const test: ValueHolder<Car, keyof Car> = {
modelKey: 'horsePower',
value: 1000,
};
在这一点上,没有发生错误,它将很好地存储值。但您也可以传递Date
类型的值:
const test: ValueHolder<Car, keyof Car> = {
modelKey: 'horsePower',
value: new Date(),
};
因为无论出于什么原因,该值都可以接受所提供模型中任何键的所有类型:
(property) ValueHolder<Car, keyof Car>.value: string | number | Date | undefined
如何才能使接口的value
键ValueHolder
只接受undefined | number
类型的值,如果您提供modelKey
horsePower
?
推荐答案
ValueHolder
第二个泛型参数H
允许所有键,从而导致允许所有值。
您需要稍微修改主实用程序类型以使非法状态不可代表。
考虑这个例子:
type Values<T> = T[keyof T]
type ValueHolder<T> = Values<{
[Prop in keyof T]: {
modelKey: Prop;
value: T[Prop]
}
}>
// type Test = {
// modelKey: "id";
// value: number;
// } | {
// modelKey: "horsePower";
// value: number | undefined;
// } | {
// modelKey: "date";
// value: Date;
// } | undefined
type Test = ValueHolder<Car>
interface Car {
id: number;
horsePower?: number;
date: Date;
};
// ok
const test: ValueHolder<Car> = {
modelKey: 'horsePower',
value: 1000,
};
// error
const test2: ValueHolder<Car> = {
modelKey: 'horsePower',
value: new Date(),
};
参见type Test
。ValueHolder
创建所有允许值的联合。它遍历每个键并创建此接口{Prop:{Model Key:p,Value:t[P]}}。然后Values
获取每个对象值{modelKey:P, value:T[P]}
并将它们合并。
更新
谢谢,效果很好!如果我希望
T[Prop]
只能是字符串类型,该怎么办?这也有可能吗?
是的。有两种方法可以实现这一点。您只能允许ValueHolder
接收值为字符串的对象。
type ValueHolder<T extends Record<string, string>> = Values<{
[Prop in keyof T]: {
modelKey: Prop;
value: T[Prop]
}
}>
或者,您可以在迭代内部检查T[Prop]
是否为字符串。
type ValueHolder<T> = Values<{
[Prop in keyof T]: T[Prop] extends string ? {
modelKey: Prop;
value: T[Prop]
} : never
}>
这篇关于与类型不匹配的打字脚本泛型键的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
查看全文