typescripttypescript-generics

Typescript narrow down generic type of const variable with inferred type


background:

by const variable with inferred type, I mean

const c = 1 // this
const c:1 = 1 // not this
const c = 1 as const // not this

related

So I am trying to narrow down the type of such variable, here is my attempt: enter image description here

does not work

enter image description here

does not work

enter image description here

export const Narrow=<T extends any>(v:T extends never ? T: T extends never ? T : T)=>{
  //
}
const c=1


Narrow(c)

this works, it looks weird, but it did the job

playground

so my question is:

  1. why?
  2. any simpler solution?
  3. any better solution?

update: as for typescript 5.0, none of the methods work anymore,just use generic cosnt keyword


Solution

  • This has now been addressed in TypeScript 5.0 with the introduction of const generics. See this pull request and the relevant issue for more information. With this, the definition of Narrow now looks like

    export const Narrow = <const T>(v: T) => {};
    
    const c = 1;
    
    Narrow(c); // inferred as Narrow<1>(v: 1)
    

    This acts in a similar manner to the Narrow type I showcased in the comments:

    type Narrow<T> =
        | (T extends infer U ? U : never)
        | Extract<T, number | string | boolean | bigint | symbol | null | undefined | []>
        | ([T] extends [[]] ? [] : { [K in keyof T]: Narrow<T[K]> });
    

    Except that it infers everything as readonly, as if you had really called the function with

    Narrow({ ... } as const)
    

    You can compare the pre-5.0 method and 5.0 const generics using the two playground links below: