microsoft / microsoft/TypeScript

Evaluate mathematical expression of indices when indexing tuples

Open
#42,693 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Awaiting More Feedback Suggestion
Dominant language
Go
Stars
111k
Forks
14.3k
Avg merge
2d 4h
Merged PRs (30d)
132

Description

Suggestion

🔍 Search Terms

tuple bounds, tuple index computing, bound checking removal, noUncheckedIndexedAccess

✅ Viability 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, new syntax sugar for JS, etc.)
  • This feature would agree with the rest of TypeScript's Design Goals.

⭐ Suggestion

Currently (version 4.1), Typescript is able to deduce that an array access to a tuple is within bounds if it is indexed by an integer literal union type that fits within the array, e.g.:

type I = 0 | 1 | 2;
function access(i: I, a: [string, string, string]) {
    return a[i];
} // type: string, even with noUncheckedIndexedAccess = true

However, as soon as there is an operation on the indexing variable, even trivial, Typescript falls back to inferring number. Therefore, the following code:

type I = 0 | 1;
function access(i: I, a: [string, string, string]) {
    return a[i + 1];
} // type: string | undefined, when noUncheckedIndexedAccess = true

In principle, Typescript could reason a bit deeper on the set of possible integer values when going through operations, especially for the trivial ones like in my example. If there is a lot of values in the union, it might be computationally expensive, but in that case a conservative bound analysis would already be enough for most uses cases (see #15480).

📃 Motivating Example

The proposed feature would at minimum allow:

type I = 0 | 1;
function access(i: I, a: [string, string, string]) {
    return a[i + 1];
}

and, if possible, use cases such as:

type Vector = [number, number];
type Matrix = [number, number, number, number];
const Range = [0, 1] as const;
function mult(m: Matrix, v: Vector) {
    let ret: Vector = [0, 0];
    for (const i of Range) {
        let acc = 0;
        for (const j of Range) {
            acc += v[j] * m[i * 2 + j];
        }
        ret[i] = acc;
    }
    return ret;
}

and, if Vector and Matrix can be aliases to fixed-size typed arrays (see #18471) in addition to tuple, it would be wonderful.

💻 Use Cases

That feature would be very useful in conjunction with noUncheckedIndexedAccess obviously, but also with a way to statically type the length of TypedArray (see #18471) for use in mathematical and graphics code. But even without typed arrays, it would still be useful in day-to-day code. I'm experimenting in switching our 45 kloc Typescript code base to noUncheckedIndexedAccess = true and that feature would increase type safety in several places.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Review the tuple-indexing examples and the related discussions in #15480 and #18471 first. Then trace the TypeScript type-checking behavior for tuple accesses under noUncheckedIndexedAccess and determine how the shown expressions should be validated. Done should include the motivating examples producing the intended non-undefined types without changing emitted JavaScript.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
compilers
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.