microsoft / TypeScript

TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
https://www.typescriptlang.org
Apache License 2.0
101.12k stars 12.5k forks source link

When the initial element of the tuple is a rest element, it is not possible to correctly infer the type of the initial element. #56885

Open 13OnTheCode opened 10 months ago

13OnTheCode commented 10 months ago

🔍 Search Terms

initial element of the tuple is a rest element

✅ Viability Checklist

⭐ Suggestion

type T1 = [...string[], number, boolean]

declare const head: T1[0]
         // Actual: string | number | boolean
         // Expected: string | number

📃 Motivating Example

-

💻 Use Cases

https://github.com/microsoft/TypeScript/issues/56883

craigphicks commented 10 months ago

Actually this is not a new feature. See #49138 which was fixed in 5.0.8. It is a bug - consider I am now assuming this is a feature request.

type T1 = [...string[], number, boolean]

const arr1: T1 = [2, true];
const arr2: T1 = ["", 2, true];
const arr3: T1 = [true]; // error
//    ~~~~
// Type '[true]' is not assignable to type 'T1'.
//  Source has 1 element(s) but target requires 2.

declare const arr: T1;
const head = arr[0]
   // Actual: string | number | boolean
   // Expected: string | number

https://www.typescriptlang.org/play?ts=5.0.4#code/FAFwngDgpgBAKgRhgXhgbQHRYM4gE4CWAdgOZoC6ANDEQK4C2ARlHtYwPbsA2UAhkeWDAAxuyK4YvPHgQAueElRoATNXy0o5ANwixEqXmXzEKdACIz1VTHWado8SEnSAzMcXpb2mAHofMFjx2PGA-GHCYAD9oyND-OEhYAHI0LySYAmwadidebGwCEiJeRh4bdhtEmCTEJIw48IBldlo8YVgACzyYJCgeeigiEAAKbABKGEZaJxApEignPCgAR1oCJazleuAAEyhhLilYB31pd3s9Jw6+HdMDNAAGQQiwgEFhEFpeLnlcQlIYAAfGgMZh4IGTTg8fjAF7+ACiAA9oB8oDtfvhiCQIXQmCwgA

craigphicks commented 10 months ago

@fatcerberus Let me clarify my statement.

I am making two assumptions:

  1. that the current assignment behavior is correct
  2. that correct indexing behavior should follow exactly the results of assignment behavior

@jcalz asserts [here]() that "Yes, that type (arr[0]) is wider than it should be, but that's not a bug, it's a design decision."

In other words, that my assumption 2 is incorrect.

Certainly there are times when economy of calculation dictates using wider types. Other times it may just be expedient coding. Either of those would enough to invalidate my assumption 2.

Therefore I will withdraw my statement that this must be a bug, and instead assume it is a feature request.

craigphicks commented 10 months ago

@13OnTheCode - As a feature request, I believe more explanation is required.

Currently, you have your motivating example code listed in the suggestion section, and the motivating example and use cases sections are empty.

Here is an example:

Suggestion

  • Tuple indexed access, start-relative or end-relative, by a literal number, should return the minimal possible type set.

You could also give an algorithm that computes that.

fatcerberus commented 10 months ago

...that correct indexing behavior should follow exactly the results of assignment behavior

Yes, this assumption is incorrect. The PR that implemented mid/lead rest elements (https://github.com/microsoft/TypeScript/pull/41544) specifically calls out the current indexing behavior, suggesting it's intentional (or at least a known-upfront design limitation).

From #41544:

Also note that indexing a tuple type beyond its starting fixed elements (if any) yields a union type of all possible element types