首页 > 解决方案 > 有没有办法在 Typescript 中制作对象的子集?

问题描述

我有一个Item这样定义的对象

type Item = {
  amount: number;
  warnLimit: number;
  prettyName: string 
}

当值是某种类型时,我正在尝试创建一个具有键值的类型:

{
  amount: number;
  warnLimit: number
} // ItemOnly<number>

但相反,我得到

{
  amount: number;
  warnLimit: number;
  prettyName: number
} // ItemOnly<number>

目前,我正在使用

type ItemOnly<T> = {
  [key in keyof Item]?: T;
};

每当我需要转换时,Item我都会这样做(item as any) as ItemOnly<number>,但这仍然允许我访问类型不正确的密钥。

我不知道这是否可能,因为我是更复杂的打字稿的新手。

标签: typescript

解决方案


根据您所写的内容,我假设您想Item根据谓词选择属性的子集。在这种情况下,谓词是:给我值为 a 的属性number

换句话说,我们想做Pick<Item, 'amount' | 'warnLimit'>但不硬编码选择的属性名称。

让我们首先创建一个按属性值定位属性的助手。

type PropertyOfValue<T, V> = {
  [K in keyof T]-?: T[K] extends V
    ? K
    : never
}[keyof T];

我们现在可以选择 的数值属性Item

type ItemOnlyNumber = Pick<Item, PropertyOfValue<Item, number>>;

但我们不必将自己限制在 type 的值上numberItemOnly<T>我们可以创建一个通过任何值选择属性的泛型类型。

type ItemOnly<T> = Pick<Item, PropertyOfValue<Item, T>>;
const item: ItemOnly<number> = {
  amount: 5,
  warnLimit: 10
}

希望有帮助!


推荐阅读