0

Is it possible to define a type foo following this pseudo-code?

type foo<T> = {
  length: number;
  array: T[length]
}

Alternatively:

type foo<T> = {
  length: array.length;
  array: T[]
}

For example, {length: 2, array: ["a","b"]} should have this type, but {length: 3, array: ["a","b"]} should not.

It has been answered before how to define a FixedLengthArray<T,N extends number> type. We can use this to define:

type foo<T,N extends number> = {
  length: N;
  array: FixedLengthArray<T,N>
}

This works when I want to define

let bar : foo<string,2> = {length: 2, array: ["a","b"]};

But my goal is to write

let bar : foo<string> = {length: 2, array: ["a","b"]};

Can we somehow let TypeScript infer the length?

Script Raccoon
  • 261
  • 2
  • 14

1 Answers1

0

TypeScript won't infer any generic parameter elsewhere than in a function call parameters. So you could use a function and variadic tuples in order to achieve that:

type Foo<U extends Array<any>, T extends [...U]> = {
    length: T['length'];
    array: T;
}

declare function handleFoo<U extends Array<any>, T extends [...U]>(param: Foo<U, T>): any;

handleFoo({ length: 3, array: ["a", "b"] }); // Error
handleFoo({ length: 2, array: ["a", "b"] }); // OK

TypeScript playground

Guerric P
  • 30,447
  • 6
  • 48
  • 86