type FunctionPropertyNames<T> = { [K in keyof T]: T[K] extends Function ? K : never }[keyof T];
I know mapped type { [P in keyof T]: T[P] } and keyof, but how do they work together and filter never?
If never is present in a union, it is removed from the union. So never | "A" will just be "A".
Given this behavior, we want to construct a mapped type that has never as the type for the keys we don't want in the result, and the name of the key as the type of the key for the keys we want in the result. We do this using the conditional type T[K] extends Function ? K : never on each property. So for example:
type FunctionPropertyNamesMapped<T> = { [K in keyof T]: T[K] extends Function ? K : never }
type Test = FunctionPropertyNamesMapped<{
a: number,
fn: () => {}
}>
// Test is the same as
// {
// a: never;
// fn: "fn";
//}
Given this new mapped type, if we get a union of all key types in it (using [keyof T]) we would get the union never | "fn" which reduces to just "fn"
You can also listen to my audio explanation of something similar here
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With