Typescript Tuple Type mapping does not work: Default Array properties are missing

479 Views Asked by At

i want to create a type that maps a tuple of shape [...T[]] into [...TodoStepBlueprint<T>[]].

my knowledge of typescript is limited but i think i understand what i did so far.

this is what i have so far: (which is an extension of How to 'map' a Tuple to another Tuple type in Typescript 3.0) using typescript (3.7.5)

interface Strategy<T extends [...TodoStepBlueprint<AbstractTodoData>[]]> {}

type MaybeType<T> = T extends AbstractTodoData ? TodoStepBlueprint<T> : never;
type MaybeTypes<Tuple extends [...AbstractTodoData[]]> = {
  [Index in keyof Tuple]: MaybeType<
    Extract<Tuple[Index], [...AbstractTodoData[]]>
  >;
} & { length: Tuple["length"] };


interface TodoStepBlueprint<
  T extends AbstractTodoData,
  K = [...AbstractTodoData[]]
> {
  readonly todoType: Constructor<T>;
  readonly name: string;
  readonly possibleNext?: Strategy<MaybeTypes<K>>;
  // naming identifier
}

this produces a typescript error:

Type 'MaybeTypes<K>' does not satisfy the constraint 'TodoStepBlueprint<AbstractTodoData, AbstractTodoData[]>[]'.
  Type 'MaybeTypes<K>' is missing the following properties from type 'TodoStepBlueprint<AbstractTodoData, AbstractTodoData[]>[]': pop, push, concat, join, and 25 more.ts(2344)

somehow typescript does not unterstand that its an array anymore. what did i do wrong?

1

There are 1 best solutions below

0
leonat On

thanks for all your responses:

this is my working solution.


interface Strategy<T extends [...TodoStepBlueprint<AbstractTodoData>[]]> {
  getPossibleNext(): T;
  getNext(): T[number];
}

type EnsureTodoStepBlueprintType<T> = T extends AbstractTodoData
  ? TodoStepBlueprint<T>
  : never;

type MapToTodoStepBlueprintArrayType<Tuple extends any[]> = {
  [Index in keyof Tuple]: EnsureTodoStepBlueprintType<Tuple[Index]>;
} & { length: Tuple["length"] };

interface TodoStepBlueprint<
  TodoType extends AbstractTodoData,
  PossibleNextTodoTypes extends AbstractTodoData[] = []
> {
  readonly todoType: Constructor<TodoType>;
  readonly name: string;
  readonly possibleNext?: Strategy<
    MapToTodoStepBlueprintArrayType<PossibleNextTodoTypes>
  >;
  // naming identifier
}