Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
408 views
in Technique[技术] by (71.8m points)

How to get a subset of `keyof T` whose value, T[K] are callable functions in Typescript

I want to filter keyof T based on type of T[keyof T]

It should work like this:

type KeyOfType<T, U> = ...

KeyOfType<{a: 1, b: '', c: 0, d: () => 1}, number> === 'a' | 'c'

KeyOfType<{a: 1, b: '', c: 0: d: () => 1}, string> === 'b'

KeyOfType<{a: 1, b: '', c: 0: d: () => 1}, Function> === 'd'

Is this possible?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

You can do this using conditional and mapped types

type KeyOfType<T, U> = {[P in keyof T]: T[P] extends U ? P: never}[keyof T]

Let's break things down a little bit.

We can start with a mapped type, that has the same properties of the same type as the original T, this a simple standard mapped type:

type KeyOfType<T> = { [P in keyof T]: T[P] } // New Type same as the original

T[P] is a type query and means the type of the key P in type T. We can change this to just P, meaning that the type of the new property is the same as it's name:

type KeyOfType<T> = { [P in keyof T]: P }
// So
KeyOfType<{ a: number, b: string }> == { a: 'a', b: 'b' }

We can add a type query to this type to again get all the keys of the type. Generally a construct T[keyof T] gets all the property types of a type. Applying this to our mapped type which has the property types the same as the key names we basically get back to keyof T:

type KeyOfType<T> = { [P in keyof T]: P }[keyof T]
// So
KeyOfType<{ a: number, b: string }> ==  'a'|'b' 

Now we can add a conditional type to o not always select P. Since A | never == A we can set the type of the property in the mapped type to never if the type of the original property (T[P]) does not meet a certain constraint.

To express the constraint we add an extra generic parameter U and we use a conditional type which has the form T extends U ? TypeIfTrue: TYpeIfFalse. Putting it together we get:

type KeyOfType<T, U> = {[P in keyof T]: T[P] extends U ? P: never}[keyof T]

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...