Search code examples
typescriptstrong-typing

Omitting keys of a particular type


Here is what I would like:

const a = getNumber({a: 3, b: "three"}, "a"); // a is type of number (or even 3)
const b = getNumber({a: 3, b: "three"}, "b"); // does not compile

The closest I have gotten is

type NumberOnly<T> = {
    [k in keyof T]: T[k] extends number ? number : never;
}
const getNumber = <T extends Record<string, any>, 
                   K extends  keyof NumberOnly<T>>(t: T, k: K):NumberOnly<T>[K] 
     => t[k];

a is type number and b is ... never.

Close but no cigar.


The suggestion here only works if the base type is fixed, which weirdly would have worked for my original problem, but if the type is generic, Typescript does not understand that t[k] is a number.


Solution

  • This should fix the problem:

    type NumberOnly<T> = {
        [K in keyof T as T[K] extends number ? K : never]: T[K]
    }
    

    We use the as operator inside the index signature. When T[K] is not number the key will be omitted.

    Playground