Typescript 泛型 keyof 与类型不匹配

2024-03-06

我有这个接口,它只存储另一个接口的密钥(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?

Demo https://tsplay.dev/NVgzBm


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(),
};

操场 https://tsplay.dev/w2ErrW

See type Test. ValueHolder创建所有允许值的并集。它迭代每个键并创建此接口 {Prop:{modelKey:P, value:T[P]}}。然后Values获取每个对象的值{modelKey:P, value:T[P]}并将它们结合起来。

UPDATE

谢谢,工作正常!如果我想要那个怎么办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
}>
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Typescript 泛型 keyof 与类型不匹配 的相关文章

随机推荐