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']>;