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
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.