Typescript: Support Recursive Conditional Types

Created on 11 Jan 2020  路  3Comments  路  Source: microsoft/TypeScript

Search Terms

recursive conditional

Suggestion

I want to be able to use recursive conditional types.

Use Cases

In this type:

type MapParams<T extends any[]> =
    ((...t: T) => any) extends ((first: string, ...tail: infer TRest) => any) ?
    Prepend<First<T>, MapParams<TRest>> :
    Partial<T>;

I am making all elements optional except for the ones at the start that are strings. This fails as MapParams references itself so I get a Type alias 'MapParams' circularly references itself.(2456) error.

Examples

type Prepend<TFirst, TRest extends any[]> =
    ((head: TFirst, ...args: TRest) => any) extends ((...args: infer U) => any)
    ? U
    : TRest;

type First<T extends any[]> = T extends [infer TFirst, ...any[]] ? TFirst : never;

type MapParams<T extends any[]> =
    ((...t: T) => any) extends ((first: string, ...tail: infer TRest) => any) ?
    Prepend<First<T>, Partial<TRest>> : // should be Prepend<First<T>, MapParams<TRest>>
    Partial<T>;

function myFunction(one: string, two: string, three: number, four: boolean) { }
function mappedFunction(...args: MapParams<Parameters<typeof myFunction>>) { }

mappedFunction("") // should NOT work - string at index 1 should be required
mappedFunction("", "") // should work
mappedFunction(undefined) // should not work
mappedFunction() // should not work

Playground

Checklist

My suggestion meets these guidelines:

  • [x] This wouldn't be a breaking change in existing TypeScript/JavaScript code
  • [x] This wouldn't change the runtime behavior of existing JavaScript code
  • [x] This could be implemented without emitting different JS based on the types of the expressions
  • [x] This isn't a runtime feature (e.g. library functionality, non-ECMAScript syntax with JavaScript output, etc.)
  • [x] This feature would agree with the rest of TypeScript's Design Goals.
Duplicate

Most helpful comment

Duplicate of #26980, but yes, please.

All 3 comments

I can up with this inelegant solution that works but only handles up to 10 params

type MapOne<T extends any[]> = ((...t: T) => any) extends ((f: string, ...t: infer TRest) => any) ? Prepend<First<T>, MapTwo<TRest>> : Partial<T>;
type MapTwo<T extends any[]> = ((...t: T) => any) extends ((f: string, ...t: infer TRest) => any) ? Prepend<First<T>, MapThree<TRest>> : Partial<T>;
type MapThree<T extends any[]> = ((...t: T) => any) extends ((f: string, ...t: infer TRest) => any) ? Prepend<First<T>, MapFour<TRest>> : Partial<T>;
type MapFour<T extends any[]> = ((...t: T) => any) extends ((f: string, ...t: infer TRest) => any) ? Prepend<First<T>, MapFive<TRest>> : Partial<T>;
type MapFive<T extends any[]> = ((...t: T) => any) extends ((f: string, ...t: infer TRest) => any) ? Prepend<First<T>, MapSix<TRest>> : Partial<T>;
type MapSix<T extends any[]> = ((...t: T) => any) extends ((f: string, ...t: infer TRest) => any) ? Prepend<First<T>, MapSeven<TRest>> : Partial<T>;
type MapSeven<T extends any[]> = ((...t: T) => any) extends ((f: string, ...t: infer TRest) => any) ? Prepend<First<T>, MapEight<TRest>> : Partial<T>;
type MapEight<T extends any[]> = ((...t: T) => any) extends ((f: string, ...t: infer TRest) => any) ? Prepend<First<T>, MapNine<TRest>> : Partial<T>;
type MapNine<T extends any[]> = ((...t: T) => any) extends ((f: string, ...t: infer TRest) => any) ? Prepend<First<T>, MapTen<TRest>> : Partial<T>;
type MapTen<T extends any[]> = ((...t: T) => any) extends ((f: string, ...t: infer TRest) => any) ? Prepend<First<T>, Partial<TRest>> : Partial<T>;

Playground

Duplicate of #26980, but yes, please.

@Roaders
Sounds like you could use trampolines (as a workaround)
https://github.com/microsoft/TypeScript/issues/26980#issuecomment-566214255

Or use ts-toolbelt and how they do recursion.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

kyasbal-1994 picture kyasbal-1994  路  3Comments

dlaberge picture dlaberge  路  3Comments

weswigham picture weswigham  路  3Comments

Antony-Jones picture Antony-Jones  路  3Comments

siddjain picture siddjain  路  3Comments