我有一个接口
export interface MyInterface { a: number; b: string; c: number; }
我想创建一个文本类型的属性名称,其值为类型数字我知道如何使用
type MyType = keyof MyInterface // gives 'a'|'b'|'c'
我只想得到“一”|'c'
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匹配的属性键。那些正好是V或V的子类型的属性键:
KeysMatching<T, V>
T
V
keyof T
K
T[K]
never
{a: "a", b: never, c: "c"}
"a" | never | "c"
"a" | "c"
interface AnotherInterface { narrower: 1; exact: number; wider: string | number; } type AnotherType = KeysMatching<AnotherInterface, number>; // type AnotherType = "narrower" | "exact"
如果你想在 * 写 * T的属性时得到与V匹配的键...也就是说,正好是V或V的 * 超类型 *,那么你需要KeysMatching的不同实现:
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"
不管怎样,希望能有所帮助,祝你好运!链接到代码
hi3rlvi22#
我不认为你可以选择属性的类型,但如果你知道你接受的属性,你可以创建一个新的类型的基础上,像这样;
type MyType = Pick<MyInterface, 'a' | 'c'>
我喜欢this blog post,它涵盖了您可以使用的大多数类型(Readonly、Partial、Required、Pick、Record、Extract、Exclude等),但我知道Omit也是最近推出的。我发现这个答案更好地解释了这一点; Exclude property from type
Readonly
Partial
Required
Pick
Record
Extract
Exclude
Omit
anauzrmj3#
我建议安装utility-types库。npm i utility-types它有一堆额外的TypeScript实用程序类型,使这样做的事情容易得多。您可能感兴趣的特定实用程序类型是PickByValueExact<ObjectType, ValueType>
npm i utility-types
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>实用程序
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>;
3条答案
按热度按时间cx6n0qe31#
您当然可以在TypeScript中定义这样的类型:
在这里,
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
匹配的属性键。那些正好是V
或V
的子类型的属性键:如果你想在 * 写 *
T
的属性时得到与V
匹配的键...也就是说,正好是V
或V
的 * 超类型 *,那么你需要KeysMatching
的不同实现:不管怎样,希望能有所帮助,祝你好运!
链接到代码
hi3rlvi22#
我不认为你可以选择属性的类型,但如果你知道你接受的属性,你可以创建一个新的类型的基础上,像这样;
我喜欢this blog post,它涵盖了您可以使用的大多数类型(
Readonly
、Partial
、Required
、Pick
、Record
、Extract
、Exclude
等),但我知道Omit
也是最近推出的。我发现这个答案更好地解释了这一点; Exclude property from type
anauzrmj3#
我建议安装utility-types库。
npm i utility-types
它有一堆额外的TypeScript实用程序类型,使这样做的事情容易得多。
您可能感兴趣的特定实用程序类型是
PickByValueExact<ObjectType, ValueType>
还有更宽松的
PickByValue<ObjectType, ValueType>
实用程序