与类型不匹配的打字脚本泛型键 [英] Typescript generics keyof doesn't match type

查看:0
本文介绍了与类型不匹配的打字脚本泛型键的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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


如何才能使接口的valueValueHolder只接受undefined | number类型的值,如果您提供modelKeyhorsePower

Demo

推荐答案

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

Playground

参见type TestValueHolder创建所有允许值的联合。它遍历每个键并创建此接口{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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆