Skip to content

Tuple with optional element and exactOptionalPropertyTypes still returns undefined during iteration #54302

Open
@jakubmazanec

Description

@jakubmazanec

Bug Report

When iterating over a variable with a tuple type with optional element [T?], the type of the item is still T | undefined even when exactOptionalPropertyTypes: true (i.e. creating a variable like let foo: [string?] = [undefined] errors).

🔎 Search Terms

tuple, optional tuple element, exactOptionalPropertyTypes

🕗 Version & Regression Information

This is the behavior in every relevant version I tried (4.4.4 to 5.1-beta), and I reviewed the FAQ for entries about tuples

⏯ Playground Link

Playground link with relevant code

💻 Code

type Item = {
    value: string;
};

type Foo = [Item?];

let foo1: Foo = []; // no error, good, there can be 0 or 1 item
let foo2: Foo = [undefined]; // error, good, because of `exactOptionalPropertyTypes: true`; if I turn this option off, the error goes away
let foo3: Foo = [{value: '1'}]; // no error, good, obviously

console.log('1');

for (let item of foo1) {
  console.log('2');
  console.log(item.value); // error, but why? `'2'` isn't logged during runtime
}

console.log('3');

console.log(foo1[0].value); // error, good, because there may be no item

console.log('4'); // this isn't logged because of runtime error on previous line

type Bar = [Item];

let bar: Bar = [{value: '1'}];

for (let item of bar) {
  console.log(item.value); // no error, good
}

🙁 Actual behavior

Error on line 15 (console.log(item.value);) because item has type Item | undefined.

🙂 Expected behavior

I would expect no error on line 15 and the type of item to be Item. Is this maybe somehow related to #51643? Or is my expectation incorrect and there's some possible runtime behavior that I'm not taking into account? But I think that e.g. noUncheckedIndexedAccess doesn't apply in this situation (and toggling it off and on didn't change anything anyway). I also tried readonly [Item?], although it too doesn't affect anything (as I think it shouldn't).

Metadata

Metadata

Assignees

No one assigned

    Labels

    BugA bug in TypeScriptHelp WantedYou can do this

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions