Search code examples
typescriptstrong-typing

Type Challenge 11 Tuple to Object


I am fairly new to strong typing but have been working in TypeScript for a little while now. I am starting to work through the Type Challenges to get better at strong typing and having a strong intuition about the type system in TypeScript.

Currently, I am wondering about the difference between these two options for declaring a type:

type TupleOptions = Array<number | string>;

type TupleOptions = (number | string)[];

My understanding is that they should be equivalent. However, I am working on 11 - Tuple to Object and seeing a difference when trying to use them.

// this works
type TupleToObject<T extends readonly (number | string)[]> = {
  [key in T[number]]: key;
}

// this does NOT work
type TupleToObject<T extends readonly Array<number | string>> = {
  [key in T[number]]: key;
}

I'm still new so this very much confuses me.

...And, beyond that issue I am interested to learn why - for this challenge - using any[] (errors) and (number | string)[] (passes) produces different results for the final test in the challenge:

// @ts-expect-error
type error = TupleToObject<[[1, 2], {}]>

Direct link to TypeScript Playground


Solution

  • Array<T> and T[] are equivalent. However, there's one special piece of syntax sugar that only works on the latter. Specifically, readonly T[] translates to ReadOnlyArray<T>. So you should regard readonly T[] as a sort of special syntax entirely distinct from T[]; the only reason it's in the language at all is that people don't like writing out a long name like Array<T> for a common type like arrays.