Home > other >  why `[true, false] extends [false, false]` in typescript, sometimes it's right, and sometime it
why `[true, false] extends [false, false]` in typescript, sometimes it's right, and sometime it

Time:10-07

why below code return ["Why?", [true, false]]? ts playground link

export type StartsWith<S extends string, SearchString extends string> = S extends `${SearchString}${infer T}` ? true : false;
export type IsNegative<N extends number> = StartsWith<`${N}`, '-'>;

export type Sub<A extends number, B extends number> = [IsNegative<A>, IsNegative<B>] extends infer R
    ?  R extends  [false, false]
        ? ['Why?', R]
        : 'Expected'
    : never;

type T0 = [IsNegative<-15>, IsNegative<90>]; // [true, false]
type T1 = Sub<-15, 90>; // ["Why?", [true, false]] /* Why [true, false] extends [false, false] ??? */

CodePudding user response:

It seems that TypeScript is lazily evaluating IsNegative, or it isn't evaluating it completely...? If we expand IsNegative to its full form:

type Sub<A extends number, B extends number> = [`${A}` extends `${"-"}${infer T}` ? true : false, `${B}` extends `${"-"}${infer T}` ? true : false] extends infer R

Then you will get "Expected".

Also, if you change the definition of IsNegative to this:

type IsNegative<N extends number> = `${N}` extends `-${number}` ? true : false;

it will also work.

So my takeaway is that TypeScript is being lazy, and "summarizes" IsNegative to true | false (basically, boolean), and then when needed, expands and evaluates the type...? At least, that's what I imagine what TypeScript is doing.

CodePudding user response:

export type Sub<A extends number, B extends number> = IsNegative<A> extends infer IsNA
    ? IsNegative<B> extends infer IsNB
        ? [IsNA, IsNB] extends infer R
            ? R extends [false, false]
                ? ['UnExpected, Why?', R]
                : 'Expected'
            : never
        : never
    : never;

work well

It seems like you can't compute too many things at once, caching the results in two steps avoids this problem.(I'm used to caching the results of some types of evaluations using Something infer Cache ? ... : never)

That's a solution I can live with for me

  • Related