Search code examples
javascripttypescripttypingmapped-typesconditional-types

Exclude object keys by their value type in TypeScript


I want to map an object type to a subtype that includes only keys whose values are of a specific type.

For example, something like ExtractNumeric<T>, where ExtractNumeric<{ str: string, num: number }> should be equivalent to the type: { num: number }

I've tried this, but it does not work:

type ExtractNumeric<T> = { [k in keyof T]: T[k] extends number ? T[k] : never }

This snippet throws a type error: let obj: ExtractNumeric<{ str: string, num: number }> = { num: 1 }

Because although the str key expects a value of never, the compiler complains about its absence.


Solution

  • Linked aticle in the comment, but in a nutshell:

    type SubType<Base, Condition> = Pick<Base, {
        [Key in keyof Base]: Base[Key] extends Condition ? Key : never
    }[keyof Base]>;
    
    type ExtractNumeric<T> = SubType<T, number>