Typescript:如何将一个类型的属性过滤为特定类型的属性?

ubbxdtey  于 2022-12-05  发布在  TypeScript
关注(0)|答案(3)|浏览(287)

我有一个接口

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

我想创建一个文本类型的属性名称,其值为类型数字
我知道如何使用

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

我只想得到“一”|'c'

cx6n0qe3

cx6n0qe31#

您当然可以在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<T, V>返回T的键集,其属性可分配给V。它使用条件和Map类型沿着属性查找。对于keyof T中的每个键K,它检查T[K]是否可分配给V。如果是,它返回键K;如果不是,它返回never。因此对于您的类型,它将类似于{a: "a", b: never, c: "c"}。然后我们查找属性值,并获得类型的并集,如"a" | never | "c",它将简化为"a" | "c",这正是您所希望的。
请注意,KeysMatching<T, V>只返回那些在 * 阅读 * 属性时其值与V匹配的属性键。那些正好是VV的子类型的属性键:

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

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

如果你想在 * 写 * T的属性时得到与V匹配的键...也就是说,正好是VV的 * 超类型 *,那么你需要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"

不管怎样,希望能有所帮助,祝你好运!
链接到代码

hi3rlvi2

hi3rlvi22#

我不认为你可以选择属性的类型,但如果你知道你接受的属性,你可以创建一个新的类型的基础上,像这样;

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

我喜欢this blog post,它涵盖了您可以使用的大多数类型(ReadonlyPartialRequiredPickRecordExtractExclude等),但我知道Omit也是最近推出的。
我发现这个答案更好地解释了这一点; Exclude property from type

anauzrmj

anauzrmj3#

我建议安装utility-types库。
npm i utility-types
它有一堆额外的TypeScript实用程序类型,使这样做的事情容易得多。
您可能感兴趣的特定实用程序类型是PickByValueExact<ObjectType, ValueType>

import { PickByValueExact } from 'utility-types';

type Props = { req: number; reqUndef: number | undefined; opt?: string; };

// Expect: { req: number }
type Props = PickByValueExact<Props, number>;
// Expect: { reqUndef: number | undefined; }
type Props = PickByValueExact<Props, number | undefined>;

还有更宽松的PickByValue<ObjectType, ValueType>实用程序

import { PickByValue } from 'utility-types';

type Props = { req: number; reqUndef: number | undefined; opt?: string; };

// Expect: { req: number }
type Props = PickByValue<Props, number>;
// Expect: { req: number; reqUndef: number | undefined; }
type Props = PickByValue<Props, number | undefined>;

相关问题