Skip to content

Should the literal number value types of const-asserted arrays' indices be inferred? #34589

Closed
@btoo

Description

@btoo

Search Terms

array tuple const assertion literal index number

Suggestion, Use Cases, and Examples

I would like to infer the index type of a const-asserted array to be that of its position in the array, rather than just number (i.e. I want the literal number type). However, I can't seem to create a way to extract this into a type, even though I know TypeScript is holding onto this information somewhere.

For example, this code follows my intuition:

const days = ['Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa'] as const;

/** "Mo" | "Tu" */
type FirstTwoDays = (typeof days)[1 | 2]

/** 7 */
type DaysCount = typeof days.length;

const impossibleDayIndex = 88;
/** Tuple type 'readonly [...]' of length '7' has no element at index '88' */
type CorrectlyErrors = (typeof days)[typeof impossibleDayIndex];

Yet here, index is of type number. Although this is understandable, given the signature of Array['forEach'], it begs the question - how could I assert, as the as const does, that index should be of type 0 | 1 | 2 | 3 | 4 | 5 | 6?

days.forEach((day, index) => {});

Likewise, how could I get this to "work"?

const indexTypeLost = days.indexOf('Tu')
/** number, rather than 2 */
type IndexTypeLost = typeof indexTypeLost

The closest I can get to achieving my desired type is with

/** number | "0" | "1" | "2" | "3" | "4" | "5" | "6" | "length" | "toString" | ... */
type IndicesOfDays = keyof typeof days;

but it's not perfect:

const convertIndexToDay = (index: IndicesOfDays) => days[index]
convertIndexToDay(impossibleDayIndex) // incorrectly does not throw an error

Checklist

My suggestion meets these guidelines:

  • [?] This wouldn't be a breaking change in existing TypeScript/JavaScript code
  • This wouldn't change the runtime behavior of existing JavaScript code
  • This could be implemented without emitting different JS based on the types of the expressions
  • This isn't a runtime feature (e.g. library functionality, non-ECMAScript syntax with JavaScript output, etc.)
  • This feature would agree with the rest of TypeScript's Design Goals.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Awaiting More FeedbackThis means we'd like to hear from more people who would be helped by this featureSuggestionAn idea for TypeScript

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions