-
Notifications
You must be signed in to change notification settings - Fork 12.9k
A union including non-iterable types is not iterable #40350
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
tests/cases/conformance/es6/destructuring/destructuringArrayBindingPatternAndAssignment4.ts(5,7): error TS2548: Type 'number[] | null' is not an array type or does not have a '[Symbol.iterator]()' method that returns an iterator. | ||
|
||
|
||
==== tests/cases/conformance/es6/destructuring/destructuringArrayBindingPatternAndAssignment4.ts (1 errors) ==== | ||
// #35497 | ||
|
||
|
||
declare const data: number[] | null; | ||
const [value] = data; // Error | ||
~~~~~~~ | ||
!!! error TS2548: Type 'number[] | null' is not an array type or does not have a '[Symbol.iterator]()' method that returns an iterator. | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
//// [destructuringArrayBindingPatternAndAssignment4.ts] | ||
// #35497 | ||
|
||
|
||
declare const data: number[] | null; | ||
const [value] = data; // Error | ||
|
||
|
||
//// [destructuringArrayBindingPatternAndAssignment4.js] | ||
"use strict"; | ||
// #35497 | ||
var __read = (this && this.__read) || function (o, n) { | ||
var m = typeof Symbol === "function" && o[Symbol.iterator]; | ||
if (!m) return o; | ||
var i = m.call(o), r, ar = [], e; | ||
try { | ||
while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value); | ||
} | ||
catch (error) { e = { error: error }; } | ||
finally { | ||
try { | ||
if (r && !r.done && (m = i["return"])) m.call(i); | ||
} | ||
finally { if (e) throw e.error; } | ||
} | ||
return ar; | ||
}; | ||
var _a = __read(data, 1), value = _a[0]; // Error |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
=== tests/cases/conformance/es6/destructuring/destructuringArrayBindingPatternAndAssignment4.ts === | ||
// #35497 | ||
|
||
|
||
declare const data: number[] | null; | ||
>data : Symbol(data, Decl(destructuringArrayBindingPatternAndAssignment4.ts, 3, 13)) | ||
|
||
const [value] = data; // Error | ||
>value : Symbol(value, Decl(destructuringArrayBindingPatternAndAssignment4.ts, 4, 7)) | ||
>data : Symbol(data, Decl(destructuringArrayBindingPatternAndAssignment4.ts, 3, 13)) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
=== tests/cases/conformance/es6/destructuring/destructuringArrayBindingPatternAndAssignment4.ts === | ||
// #35497 | ||
|
||
|
||
declare const data: number[] | null; | ||
>data : number[] | null | ||
>null : null | ||
|
||
const [value] = data; // Error | ||
>value : any | ||
>data : number[] | null | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
//// [generatorReturnTypeIndirectReferenceToGlobalType.ts] | ||
interface I1 extends Iterator<0, 1, 2> {} | ||
|
||
function* f1(): I1 { | ||
const a = yield 0; | ||
return 1; | ||
} | ||
|
||
|
||
//// [generatorReturnTypeIndirectReferenceToGlobalType.js] | ||
"use strict"; | ||
function* f1() { | ||
const a = yield 0; | ||
return 1; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
=== tests/cases/conformance/generators/generatorReturnTypeIndirectReferenceToGlobalType.ts === | ||
interface I1 extends Iterator<0, 1, 2> {} | ||
>I1 : Symbol(I1, Decl(generatorReturnTypeIndirectReferenceToGlobalType.ts, 0, 0)) | ||
>Iterator : Symbol(Iterator, Decl(lib.es2015.iterable.d.ts, --, --)) | ||
|
||
function* f1(): I1 { | ||
>f1 : Symbol(f1, Decl(generatorReturnTypeIndirectReferenceToGlobalType.ts, 0, 41)) | ||
>I1 : Symbol(I1, Decl(generatorReturnTypeIndirectReferenceToGlobalType.ts, 0, 0)) | ||
|
||
const a = yield 0; | ||
>a : Symbol(a, Decl(generatorReturnTypeIndirectReferenceToGlobalType.ts, 3, 7)) | ||
|
||
return 1; | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
=== tests/cases/conformance/generators/generatorReturnTypeIndirectReferenceToGlobalType.ts === | ||
interface I1 extends Iterator<0, 1, 2> {} | ||
|
||
function* f1(): I1 { | ||
>f1 : () => I1 | ||
|
||
const a = yield 0; | ||
>a : 2 | ||
>yield 0 : 2 | ||
>0 : 0 | ||
|
||
return 1; | ||
>1 : 1 | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -25,11 +25,11 @@ declare function f2<T, R, S>(gen: () => Generator<R, T, S> | AsyncGenerator<R, T | |
f2<0, 0, 1>(async function* () { | ||
>f2<0, 0, 1>(async function* () { const a = yield 0; return 0;}) : void | ||
>f2 : <T, R, S>(gen: () => Generator<R, T, S> | AsyncGenerator<R, T, S>) => void | ||
>async function* () { const a = yield 0; return 0;} : () => AsyncGenerator<0, 0, 1> | ||
>async function* () { const a = yield 0; return 0;} : () => AsyncGenerator<0, 0, 1 | undefined> | ||
|
||
const a = yield 0; | ||
>a : 1 | ||
>yield 0 : 1 | ||
>a : 1 | undefined | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In a sense, this is not wrong— Now, when we try to get the iteration types of More work could be done to make union signatures take the fast path that drops the optionality if every signature in the union is a reference to one of the global generator/iterator types, but I felt like this was getting fairly complex for limited utility—the results it produces with less complexity are strictly more correct given the limitations we have for modeling this. |
||
>yield 0 : 1 | undefined | ||
>0 : 0 | ||
|
||
return 0; | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
// #35497 | ||
|
||
// @target: es5 | ||
// @downlevelIteration: true | ||
// @lib: es6 | ||
// @strict: true | ||
|
||
declare const data: number[] | null; | ||
const [value] = data; // Error |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
// @strict: true | ||
// @target: esnext | ||
|
||
interface I1 extends Iterator<0, 1, 2> {} | ||
|
||
function* f1(): I1 { | ||
const a = yield 0; | ||
return 1; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The reason I kept looping was to provide some kind of useful type for iteration once they fixed the error. The problem the issue mentioned was that no error was reported.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(btw: I'm not saying this change is wrong, just expressing the reasoning behind the existing logic).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, that makes sense in theory, but the problem here was that
errorNode
was intentionally not supplied, so the non-iterableness of the type was completely lost.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What do you think about the baseline change?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems fine. I do wonder about the
| null
case. If it weredata[Symbol.iterator]()
we would have errored ondata
withObject is possibly 'null'.
.