Home > Enterprise >  Typescript. Wrong generic parameter constraint in conditional type
Typescript. Wrong generic parameter constraint in conditional type

Time:03-03

Consider such type

type Last<TProps> =
TProps extends [infer TProp]
  ? TProp
  : TProps extends [infer TProp, ... infer Rest] & PropertyKey[]
    ? Last<Rest>
    : never;

export type L0 = Last<['a']>;           // 'a'
export type L1 = Last<['a', 'b']>;      // 'b'
export type L2 = Last<['a', 'b', 'c']>; // 'c'

It work as I expected. But if I want to restrict generic parameter - it fails

type Last<TProps extends PropertyKey[]> =
TProps extends [infer TProp]
  ? TProp
  : TProps extends [infer TProp, ... infer Rest]
    ? Last<Rest> // error. 'Rest' does not satisfy the constraint 'PropertyKey[]'
    : never;

I tried to use & - it give no error, but output is not what i expected

type Last<TProps extends PropertyKey[]> =
TProps extends [infer TProp]
  ? TProp
  : TProps extends [infer TProp, ... infer Rest]
    ? Last<Rest & PropertyKey[]> // no error
    : never;

export type L0 = Last<['a']>;           // 'a'
export type L1 = Last<['a', 'b']>;      // string | number | symbol
export type L2 = Last<['a', 'b', 'c']>; // never

How I can use generic type constraint in conditional type to obtain such output

type Last<TProps extends PropertyKey[]> = ????

export type L0 = Last<['a']>;           // 'a'
export type L1 = Last<['a', 'b']>;      // 'b'
export type L2 = Last<['a', 'b', 'c']>; // 'c'

P.S. I know that in this example this constraint doesn't have much sense, but it is simpliest example that I find.

CodePudding user response:

You just need to check whether or not the inferred Rest is constrained by the extra type:

type Last<TProps extends PropertyKey[]> =
TProps extends [infer TProp]
  ? TProp
  : TProps extends [infer TProp, ... infer Rest] & PropertyKey[]
    ? Rest extends PropertyKey[]
      ? Last<Rest>
      : never
    : never;

export type L0 = Last<['a']>;
export type L1 = Last<['a', 'b']>;
export type L2 = Last<['a', 'b', 'c']>;

TS Playground

  • Related