1

I have the following code:

const arr = [1, 2, 3] as const;

type Keys = keyof typeof arr;

type T = {
  [K in Keys]: K extends 1 ? 2 : 3 // dummy
}

Why does the T type contain the prototype keys:

enter image description here

I'm expecting the keys to be only 0, 1, 2 in this case. How can I get only the array keys?

How can we create a new type from an array by looping over its keys?

undefined
  • 6,366
  • 12
  • 46
  • 90

1 Answers1

2
  1. Why K extends 1 does not evaluate to true ?

Because TS should be consistent with pure javascript property access algorithm. See MDN docs.

property names are string or Symbol. Any other value, including a number, is coerced to a string. This outputs 'value', since 1 is coerced into '1'.

Despite the fact that arrays/tuples are indexed by number, all their indexes are stringified under the hood of JS engine. This is why const result = arr['1'] // 2 is perfectly valid from TS point of view.

All number keys are de-facto strings.

See this exmaple:

declare var record: Record<number, string>

const result = record['2'] // string
const result2 = record[2] // string
const result3 = record['hello'] // expected error
  1. How can I get only the array keys? - this is a duplicate of this answer

  2. Can you explain why you're doing:

T extends ${number} instead of T extends number?

Example:

type FilterNumbers<T extends PropertyKey> = T extends `${number}` ? T : never

T extends ${number}`` - literally means if T extends a stringified number.

Here you have another one example:

type StringNumber<T extends `${number}`> = T

type Test = StringNumber<'42'> // ok

type Test1 = StringNumber<'-0.3'> // ok
type Test2 = StringNumber<`${typeof NaN}`> // ok, but in fact is a drawback
type Test3 = StringNumber<`01`> // ok, but also drawback

type Test4 = StringNumber<'hello'> // error

PLayground