【问题标题】:Typescript: How do you filter a type's properties to those of a certain type?Typescript:如何将类型的属性过滤为特定类型的属性?
【发布时间】:2021-04-11 11:11:36
【问题描述】:

我有一个界面

export interface MyInterface {
    a: number;
    b: string;
    c: number;
}

我想创建一个属性名称的文字类型,其值为 number 类型

我知道如何使用所有属性名称获取类型

type MyType = keyof MyInterface // gives 'a'|'b'|'c'

我只想得到'a'|'c'

【问题讨论】:

标签: typescript


【解决方案1】:

你当然可以在 TypeScript 中定义这样的类型:

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

type MyType = KeysMatching<MyInterface, number>;
// type MyType = "a" | "c"

在此,KeysMatching&lt;T, V&gt; 返回T 的键集,其属性可分配给V。它使用conditionalmapped 类型以及属性lookup。对于keyof T 中的每个键K,它检查T[K] 是否可分配给V。如果是,则返回密钥K;如果不是,则返回never。因此,对于您的类型,它类似于{a: "a", b: never, c: "c"}。然后我们查找属性值并得到一个类型的联合,如"a" | never | "c",它减少为"a" | "c",完全符合您的要求。

请注意KeysMatching&lt;T, V&gt; 仅在读取 属性时返回值与V 匹配的那些属性键。那些恰好是VV 的子类型:

interface AnotherInterface {
  narrower: 1;
  exact: number;
  wider: string | number;
}

type AnotherType = KeysMatching<AnotherInterface, number>;
// type AnotherType = "narrower" | "exact"

如果您想在编写 T... 的属性时获得与V 匹配的键...也就是说,恰好是V超类型 V,那么你需要 KeysMatching 的不同实现:

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

type AnotherTypeWrite = KeysMatchingWrite<AnotherInterface, number>;
// type AnotherTypeWrite = "exact" | "wider"

无论如何,希望对您有所帮助。祝你好运!

Link to code

【讨论】:

  • 该死!这真是太神奇了。我将删除我的答案。
  • 我在哪里可以了解更多关于您的类型定义中的 - 的信息?
  • this;它正在删除可能存在的任何可选修饰符,以免在键列表中获得undefined
【解决方案2】:

不要认为您可以按类型选择属性,但如果您知道您接受的属性,您可以基于此类创建新类型;

type MyType = Pick<MyInterface, 'a' | 'c'>

我喜欢this blog post,它涵盖了您可以使用的大多数类型(ReadonlyPartialRequiredPickRecordExtractExclude 等),但我知道Omit最近也有介绍。

我发现这个答案可以更好地解释它; Exclude property from type

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-01-01
    • 1970-01-01
    • 2019-09-23
    • 2021-01-22
    • 1970-01-01
    • 2022-08-11
    • 2018-10-26
    • 2022-11-02
    相关资源
    最近更新 更多