好吧,我想出了如何做到这一点,我确信有一种更优化的方式来组合这些类型转换,但这是我目前拥有的并且它有效:
type PromiseFunc = () => Promise<unknown>;
// A type whose keys we want to drop.
type SomeOtherType1 = {
key1: string[];
};
// Another type whose keys we want to drop.
type SomeOtherType2 = {
key1: number;
};
type A = {
key1: string;
key2: string;
key3: PromiseFunc;
key4: string;
key5: PromiseFunc;
key6: SomeOtherType1[];
key7: SomeOtherType2[];
key8: string;
key9: PromiseFunc;
};
// Start by building a filter type we can call with the types we want
// and converting all other types to a standard type.
type Filter<T, ConditionOne, ConditionTwo> = {
[Key in keyof T]: T[Key] extends ConditionOne
? string
: T[Key] extends ConditionTwo
? string
: number;
};
// Do the conversion to a new type that only has string and number types.
type ConvertedType = Filter<A, string, PromiseFunc>;
// Now that we only have two types we can drop all the types that don't
// match the type we want (which is string), we'll convert all those keys
// to never which will drop them from our new type.
type PickByValueType<T, U> = {
[K in keyof T as K extends K ? (T[K] extends U ? K : never) : never]: T[K];
};
// Generate the final type that is only the keys which are strings.
type FilteredType = PickByValueType<ConvertedType, string>;
我遇到的主要问题是我有number 我最初有never 我认为应该自动从类型中排除这些键,但它没有(它只是将类型更改为从不)。查看this issue on the TS issue tracker 提供了一些见解。显然这是在我正在使用的 TS 4.1.2 中,但我肯定还是做错了,如果Filter 类型与PickByValueType 类型结合使用,我相信这可以进一步优化。
对于以后可能遇到此答案的任何人,这里必须使用两种类型转换的原因是因为我们需要考虑和转换多种类型。如果你想简单地包含几种类型,你可以这样做:
...
type GrabTypes<T, U, U2> = {
[K in keyof T as K extends K
? T[K] extends U
? K
: T[K] extends U2
? K
: never
: never]: T[K];
};
type GrabbedTypes = GrabTypes<A, string, SomeOtherType1[]>
已经有几个关于使用omit 排除某些类型的问题,但我找不到很多好的例子可以让你删除不同类型的多个键。我认为这也可以以某种方式扩展以处理转换,但我想不出如何在三元运算符的约束下做到这一点:
...
type GrabTypesAndConvertOne<T, U, TypeToConvert> = {
[K in keyof T as K extends K
? T[K] extends U
? K
: T[K] extends TypeToConvert
? K // <- Here is where the type change logic would live
: never
: never]: T[K];
};
type GrabbedTypes = GrabTypesAndConvertOne<A, string, PromiseFunc>