diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 48bc0da113816..1ccf37332706c 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -45830,19 +45830,20 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { * the `[Symbol.asyncIterator]()` method first, and then the `[Symbol.iterator]()` method. */ function getIterationTypesOfIterable(type: Type, use: IterationUse, errorNode: Node | undefined) { - if (type === silentNeverType) { + const reducedType = getReducedType(type); + if (reducedType === silentNeverType) { return silentNeverIterationTypes; } - if (isTypeAny(type)) { + if (isTypeAny(reducedType)) { return anyIterationTypes; } - if (!(type.flags & TypeFlags.Union)) { + if (!(reducedType.flags & TypeFlags.Union)) { const errorOutputContainer: ErrorOutputContainer | undefined = errorNode ? { errors: undefined, skipLogging: true } : undefined; - const iterationTypes = getIterationTypesOfIterableWorker(type, use, errorNode, errorOutputContainer); + const iterationTypes = getIterationTypesOfIterableWorker(reducedType, use, errorNode, errorOutputContainer); if (iterationTypes === noIterationTypes) { if (errorNode) { - const rootDiag = reportTypeNotIterableError(errorNode, type, !!(use & IterationUse.AllowsAsyncIterablesFlag)); + const rootDiag = reportTypeNotIterableError(errorNode, reducedType, !!(use & IterationUse.AllowsAsyncIterablesFlag)); if (errorOutputContainer?.errors) { addRelatedInfo(rootDiag, ...errorOutputContainer.errors); } @@ -45858,21 +45859,21 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } const cacheKey = use & IterationUse.AllowsAsyncIterablesFlag ? "iterationTypesOfAsyncIterable" : "iterationTypesOfIterable"; - const cachedTypes = getCachedIterationTypes(type, cacheKey); + const cachedTypes = getCachedIterationTypes(reducedType, cacheKey); if (cachedTypes) return cachedTypes === noIterationTypes ? undefined : cachedTypes; let allIterationTypes: IterationTypes[] | undefined; - for (const constituent of (type as UnionType).types) { + for (const constituent of (reducedType as UnionType).types) { const errorOutputContainer: ErrorOutputContainer | undefined = errorNode ? { errors: undefined } : undefined; const iterationTypes = getIterationTypesOfIterableWorker(constituent, use, errorNode, errorOutputContainer); if (iterationTypes === noIterationTypes) { if (errorNode) { - const rootDiag = reportTypeNotIterableError(errorNode, type, !!(use & IterationUse.AllowsAsyncIterablesFlag)); + const rootDiag = reportTypeNotIterableError(errorNode, reducedType, !!(use & IterationUse.AllowsAsyncIterablesFlag)); if (errorOutputContainer?.errors) { addRelatedInfo(rootDiag, ...errorOutputContainer.errors); } } - setCachedIterationTypes(type, cacheKey, noIterationTypes); + setCachedIterationTypes(reducedType, cacheKey, noIterationTypes); return undefined; } else if (errorOutputContainer?.errors?.length) { @@ -45885,7 +45886,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } const iterationTypes = allIterationTypes ? combineIterationTypes(allIterationTypes) : noIterationTypes; - setCachedIterationTypes(type, cacheKey, iterationTypes); + setCachedIterationTypes(reducedType, cacheKey, iterationTypes); return iterationTypes === noIterationTypes ? undefined : iterationTypes; } diff --git a/tests/baselines/reference/iterableWithNeverAsUnionMember(target=es5).symbols b/tests/baselines/reference/iterableWithNeverAsUnionMember(target=es5).symbols new file mode 100644 index 0000000000000..edd180813e5e3 --- /dev/null +++ b/tests/baselines/reference/iterableWithNeverAsUnionMember(target=es5).symbols @@ -0,0 +1,94 @@ +//// [tests/cases/compiler/iterableWithNeverAsUnionMember.ts] //// + +=== iterableWithNeverAsUnionMember.ts === +declare const o1: { a: "foo" } & { a: "bar" }; +>o1 : Symbol(o1, Decl(iterableWithNeverAsUnionMember.ts, 0, 13)) +>a : Symbol(a, Decl(iterableWithNeverAsUnionMember.ts, 0, 19)) +>a : Symbol(a, Decl(iterableWithNeverAsUnionMember.ts, 0, 34)) + +const [el1] = o1; // error +>el1 : Symbol(el1, Decl(iterableWithNeverAsUnionMember.ts, 1, 7)) +>o1 : Symbol(o1, Decl(iterableWithNeverAsUnionMember.ts, 0, 13)) + +// https://github.com/microsoft/TypeScript/issues/62462 +declare var x: number[] | ({ t: "a" } & { t: "b" }); +>x : Symbol(x, Decl(iterableWithNeverAsUnionMember.ts, 4, 11)) +>t : Symbol(t, Decl(iterableWithNeverAsUnionMember.ts, 4, 28)) +>t : Symbol(t, Decl(iterableWithNeverAsUnionMember.ts, 4, 41)) + +let [el2] = x; // ok +>el2 : Symbol(el2, Decl(iterableWithNeverAsUnionMember.ts, 5, 5)) +>x : Symbol(x, Decl(iterableWithNeverAsUnionMember.ts, 4, 11)) + +for (const elem of x) { // ok +>elem : Symbol(elem, Decl(iterableWithNeverAsUnionMember.ts, 7, 10)) +>x : Symbol(x, Decl(iterableWithNeverAsUnionMember.ts, 4, 11)) + + elem.toFixed(); +>elem.toFixed : Symbol(Number.toFixed, Decl(lib.es5.d.ts, --, --)) +>elem : Symbol(elem, Decl(iterableWithNeverAsUnionMember.ts, 7, 10)) +>toFixed : Symbol(Number.toFixed, Decl(lib.es5.d.ts, --, --)) +} + +type Shape = +>Shape : Symbol(Shape, Decl(iterableWithNeverAsUnionMember.ts, 9, 1)) + + | { kind: "circle"; radius: number } +>kind : Symbol(kind, Decl(iterableWithNeverAsUnionMember.ts, 12, 5)) +>radius : Symbol(radius, Decl(iterableWithNeverAsUnionMember.ts, 12, 21)) + + | { kind: "rectangle"; width: number; height: number }; +>kind : Symbol(kind, Decl(iterableWithNeverAsUnionMember.ts, 13, 5)) +>width : Symbol(width, Decl(iterableWithNeverAsUnionMember.ts, 13, 24)) +>height : Symbol(height, Decl(iterableWithNeverAsUnionMember.ts, 13, 39)) + +type Circle = Shape & { kind: "circle" }; +>Circle : Symbol(Circle, Decl(iterableWithNeverAsUnionMember.ts, 13, 57)) +>Shape : Symbol(Shape, Decl(iterableWithNeverAsUnionMember.ts, 9, 1)) +>kind : Symbol(kind, Decl(iterableWithNeverAsUnionMember.ts, 15, 23)) + +function doStuffWithCircle(arg: Circle | [Circle, (newValue: Circle) => void]) { +>doStuffWithCircle : Symbol(doStuffWithCircle, Decl(iterableWithNeverAsUnionMember.ts, 15, 41)) +>arg : Symbol(arg, Decl(iterableWithNeverAsUnionMember.ts, 17, 27)) +>Circle : Symbol(Circle, Decl(iterableWithNeverAsUnionMember.ts, 13, 57)) +>Circle : Symbol(Circle, Decl(iterableWithNeverAsUnionMember.ts, 13, 57)) +>newValue : Symbol(newValue, Decl(iterableWithNeverAsUnionMember.ts, 17, 51)) +>Circle : Symbol(Circle, Decl(iterableWithNeverAsUnionMember.ts, 13, 57)) + + if (Array.isArray(arg)) { +>Array.isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --)) +>Array : Symbol(Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) +>isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --)) +>arg : Symbol(arg, Decl(iterableWithNeverAsUnionMember.ts, 17, 27)) + + let [value, setValue] = arg; // ok +>value : Symbol(value, Decl(iterableWithNeverAsUnionMember.ts, 19, 9)) +>setValue : Symbol(setValue, Decl(iterableWithNeverAsUnionMember.ts, 19, 15)) +>arg : Symbol(arg, Decl(iterableWithNeverAsUnionMember.ts, 17, 27)) + } +} + +function f1(x: T) { +>f1 : Symbol(f1, Decl(iterableWithNeverAsUnionMember.ts, 21, 1)) +>T : Symbol(T, Decl(iterableWithNeverAsUnionMember.ts, 23, 12)) +>a : Symbol(a, Decl(iterableWithNeverAsUnionMember.ts, 23, 23)) +>a : Symbol(a, Decl(iterableWithNeverAsUnionMember.ts, 23, 38)) +>x : Symbol(x, Decl(iterableWithNeverAsUnionMember.ts, 23, 51)) +>T : Symbol(T, Decl(iterableWithNeverAsUnionMember.ts, 23, 12)) + + let [y] = x; // error +>y : Symbol(y, Decl(iterableWithNeverAsUnionMember.ts, 24, 7)) +>x : Symbol(x, Decl(iterableWithNeverAsUnionMember.ts, 23, 51)) +} + +declare const o2: ({ a: "foo" } & { a: "bar" }) | ({ b: "qwe" } & { b: "rty" }); +>o2 : Symbol(o2, Decl(iterableWithNeverAsUnionMember.ts, 27, 13)) +>a : Symbol(a, Decl(iterableWithNeverAsUnionMember.ts, 27, 20)) +>a : Symbol(a, Decl(iterableWithNeverAsUnionMember.ts, 27, 35)) +>b : Symbol(b, Decl(iterableWithNeverAsUnionMember.ts, 27, 52)) +>b : Symbol(b, Decl(iterableWithNeverAsUnionMember.ts, 27, 67)) + +const [el3] = o2; // error +>el3 : Symbol(el3, Decl(iterableWithNeverAsUnionMember.ts, 28, 7)) +>o2 : Symbol(o2, Decl(iterableWithNeverAsUnionMember.ts, 27, 13)) + diff --git a/tests/baselines/reference/iterableWithNeverAsUnionMember(target=es5).types b/tests/baselines/reference/iterableWithNeverAsUnionMember(target=es5).types new file mode 100644 index 0000000000000..b3bb98e8ea674 --- /dev/null +++ b/tests/baselines/reference/iterableWithNeverAsUnionMember(target=es5).types @@ -0,0 +1,138 @@ +//// [tests/cases/compiler/iterableWithNeverAsUnionMember.ts] //// + +=== iterableWithNeverAsUnionMember.ts === +declare const o1: { a: "foo" } & { a: "bar" }; +>o1 : never +> : ^^^^^ +>a : "foo" +> : ^^^^^ +>a : "bar" +> : ^^^^^ + +const [el1] = o1; // error +>el1 : never +> : ^^^^^ +>o1 : never +> : ^^^^^ + +// https://github.com/microsoft/TypeScript/issues/62462 +declare var x: number[] | ({ t: "a" } & { t: "b" }); +>x : number[] +> : ^^^^^^^^ +>t : "a" +> : ^^^ +>t : "b" +> : ^^^ + +let [el2] = x; // ok +>el2 : number +> : ^^^^^^ +>x : number[] +> : ^^^^^^^^ + +for (const elem of x) { // ok +>elem : number +> : ^^^^^^ +>x : number[] +> : ^^^^^^^^ + + elem.toFixed(); +>elem.toFixed() : string +> : ^^^^^^ +>elem.toFixed : (fractionDigits?: number) => string +> : ^ ^^^ ^^^^^ +>elem : number +> : ^^^^^^ +>toFixed : (fractionDigits?: number) => string +> : ^ ^^^ ^^^^^ +} + +type Shape = +>Shape : Shape +> : ^^^^^ + + | { kind: "circle"; radius: number } +>kind : "circle" +> : ^^^^^^^^ +>radius : number +> : ^^^^^^ + + | { kind: "rectangle"; width: number; height: number }; +>kind : "rectangle" +> : ^^^^^^^^^^^ +>width : number +> : ^^^^^^ +>height : number +> : ^^^^^^ + +type Circle = Shape & { kind: "circle" }; +>Circle : { kind: "circle"; radius: number; } & { kind: "circle"; } +> : ^^^^^^^^ ^^^^^^^^^^ ^^^^^^^^^^^^^^ ^^^ +>kind : "circle" +> : ^^^^^^^^ + +function doStuffWithCircle(arg: Circle | [Circle, (newValue: Circle) => void]) { +>doStuffWithCircle : (arg: Circle | [Circle, (newValue: Circle) => void]) => void +> : ^ ^^ ^^^^^^^^^ +>arg : ({ kind: "circle"; radius: number; } & { kind: "circle"; }) | [{ kind: "circle"; radius: number; } & { kind: "circle"; }, (newValue: Circle) => void] +> : ^^^^^^^^^ ^^^^^^^^^^ ^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^ ^^^^^^^^^^ ^^^^^^^^^^^^^^ ^^^^^^ ^^ ^^^^^ ^ +>newValue : { kind: "circle"; radius: number; } & { kind: "circle"; } +> : ^^^^^^^^ ^^^^^^^^^^ ^^^^^^^^^^^^^^ ^^^ + + if (Array.isArray(arg)) { +>Array.isArray(arg) : boolean +> : ^^^^^^^ +>Array.isArray : (arg: any) => arg is any[] +> : ^ ^^ ^^^^^ +>Array : ArrayConstructor +> : ^^^^^^^^^^^^^^^^ +>isArray : (arg: any) => arg is any[] +> : ^ ^^ ^^^^^ +>arg : ({ kind: "circle"; radius: number; } & { kind: "circle"; }) | [{ kind: "circle"; radius: number; } & { kind: "circle"; }, (newValue: Circle) => void] +> : ^^^^^^^^^ ^^^^^^^^^^ ^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^ ^^^^^^^^^^ ^^^^^^^^^^^^^^ ^^^^^^ ^^ ^^^^^ ^ + + let [value, setValue] = arg; // ok +>value : { kind: "circle"; radius: number; } & { kind: "circle"; } +> : ^^^^^^^^ ^^^^^^^^^^ ^^^^^^^^^^^^^^ ^^^ +>setValue : (newValue: Circle) => void +> : ^ ^^ ^^^^^ +>arg : [{ kind: "circle"; radius: number; } & { kind: "circle"; }, (newValue: Circle) => void] +> : ^^^^^^^^^ ^^^^^^^^^^ ^^^^^^^^^^^^^^ ^^^^^^ ^^ ^^^^^ ^ + } +} + +function f1(x: T) { +>f1 : (x: T) => void +> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^^^^^ +>a : "foo" +> : ^^^^^ +>a : "bar" +> : ^^^^^ +>x : T +> : ^ + + let [y] = x; // error +>y : never +> : ^^^^^ +>x : T +> : ^ +} + +declare const o2: ({ a: "foo" } & { a: "bar" }) | ({ b: "qwe" } & { b: "rty" }); +>o2 : never +> : ^^^^^ +>a : "foo" +> : ^^^^^ +>a : "bar" +> : ^^^^^ +>b : "qwe" +> : ^^^^^ +>b : "rty" +> : ^^^^^ + +const [el3] = o2; // error +>el3 : never +> : ^^^^^ +>o2 : never +> : ^^^^^ + diff --git a/tests/baselines/reference/iterableWithNeverAsUnionMember(target=esnext).errors.txt b/tests/baselines/reference/iterableWithNeverAsUnionMember(target=esnext).errors.txt new file mode 100644 index 0000000000000..dcc7b537d3f34 --- /dev/null +++ b/tests/baselines/reference/iterableWithNeverAsUnionMember(target=esnext).errors.txt @@ -0,0 +1,41 @@ +iterableWithNeverAsUnionMember.ts(2,7): error TS2488: Type 'never' must have a '[Symbol.iterator]()' method that returns an iterator. +iterableWithNeverAsUnionMember.ts(25,7): error TS2488: Type 'T' must have a '[Symbol.iterator]()' method that returns an iterator. +iterableWithNeverAsUnionMember.ts(29,7): error TS2488: Type 'never' must have a '[Symbol.iterator]()' method that returns an iterator. + + +==== iterableWithNeverAsUnionMember.ts (3 errors) ==== + declare const o1: { a: "foo" } & { a: "bar" }; + const [el1] = o1; // error + ~~~~~ +!!! error TS2488: Type 'never' must have a '[Symbol.iterator]()' method that returns an iterator. + + // https://github.com/microsoft/TypeScript/issues/62462 + declare var x: number[] | ({ t: "a" } & { t: "b" }); + let [el2] = x; // ok + + for (const elem of x) { // ok + elem.toFixed(); + } + + type Shape = + | { kind: "circle"; radius: number } + | { kind: "rectangle"; width: number; height: number }; + + type Circle = Shape & { kind: "circle" }; + + function doStuffWithCircle(arg: Circle | [Circle, (newValue: Circle) => void]) { + if (Array.isArray(arg)) { + let [value, setValue] = arg; // ok + } + } + + function f1(x: T) { + let [y] = x; // error + ~~~ +!!! error TS2488: Type 'T' must have a '[Symbol.iterator]()' method that returns an iterator. + } + + declare const o2: ({ a: "foo" } & { a: "bar" }) | ({ b: "qwe" } & { b: "rty" }); + const [el3] = o2; // error + ~~~~~ +!!! error TS2488: Type 'never' must have a '[Symbol.iterator]()' method that returns an iterator. \ No newline at end of file diff --git a/tests/baselines/reference/iterableWithNeverAsUnionMember(target=esnext).symbols b/tests/baselines/reference/iterableWithNeverAsUnionMember(target=esnext).symbols new file mode 100644 index 0000000000000..f22ae4c1bb287 --- /dev/null +++ b/tests/baselines/reference/iterableWithNeverAsUnionMember(target=esnext).symbols @@ -0,0 +1,94 @@ +//// [tests/cases/compiler/iterableWithNeverAsUnionMember.ts] //// + +=== iterableWithNeverAsUnionMember.ts === +declare const o1: { a: "foo" } & { a: "bar" }; +>o1 : Symbol(o1, Decl(iterableWithNeverAsUnionMember.ts, 0, 13)) +>a : Symbol(a, Decl(iterableWithNeverAsUnionMember.ts, 0, 19)) +>a : Symbol(a, Decl(iterableWithNeverAsUnionMember.ts, 0, 34)) + +const [el1] = o1; // error +>el1 : Symbol(el1, Decl(iterableWithNeverAsUnionMember.ts, 1, 7)) +>o1 : Symbol(o1, Decl(iterableWithNeverAsUnionMember.ts, 0, 13)) + +// https://github.com/microsoft/TypeScript/issues/62462 +declare var x: number[] | ({ t: "a" } & { t: "b" }); +>x : Symbol(x, Decl(iterableWithNeverAsUnionMember.ts, 4, 11)) +>t : Symbol(t, Decl(iterableWithNeverAsUnionMember.ts, 4, 28)) +>t : Symbol(t, Decl(iterableWithNeverAsUnionMember.ts, 4, 41)) + +let [el2] = x; // ok +>el2 : Symbol(el2, Decl(iterableWithNeverAsUnionMember.ts, 5, 5)) +>x : Symbol(x, Decl(iterableWithNeverAsUnionMember.ts, 4, 11)) + +for (const elem of x) { // ok +>elem : Symbol(elem, Decl(iterableWithNeverAsUnionMember.ts, 7, 10)) +>x : Symbol(x, Decl(iterableWithNeverAsUnionMember.ts, 4, 11)) + + elem.toFixed(); +>elem.toFixed : Symbol(Number.toFixed, Decl(lib.es5.d.ts, --, --)) +>elem : Symbol(elem, Decl(iterableWithNeverAsUnionMember.ts, 7, 10)) +>toFixed : Symbol(Number.toFixed, Decl(lib.es5.d.ts, --, --)) +} + +type Shape = +>Shape : Symbol(Shape, Decl(iterableWithNeverAsUnionMember.ts, 9, 1)) + + | { kind: "circle"; radius: number } +>kind : Symbol(kind, Decl(iterableWithNeverAsUnionMember.ts, 12, 5)) +>radius : Symbol(radius, Decl(iterableWithNeverAsUnionMember.ts, 12, 21)) + + | { kind: "rectangle"; width: number; height: number }; +>kind : Symbol(kind, Decl(iterableWithNeverAsUnionMember.ts, 13, 5)) +>width : Symbol(width, Decl(iterableWithNeverAsUnionMember.ts, 13, 24)) +>height : Symbol(height, Decl(iterableWithNeverAsUnionMember.ts, 13, 39)) + +type Circle = Shape & { kind: "circle" }; +>Circle : Symbol(Circle, Decl(iterableWithNeverAsUnionMember.ts, 13, 57)) +>Shape : Symbol(Shape, Decl(iterableWithNeverAsUnionMember.ts, 9, 1)) +>kind : Symbol(kind, Decl(iterableWithNeverAsUnionMember.ts, 15, 23)) + +function doStuffWithCircle(arg: Circle | [Circle, (newValue: Circle) => void]) { +>doStuffWithCircle : Symbol(doStuffWithCircle, Decl(iterableWithNeverAsUnionMember.ts, 15, 41)) +>arg : Symbol(arg, Decl(iterableWithNeverAsUnionMember.ts, 17, 27)) +>Circle : Symbol(Circle, Decl(iterableWithNeverAsUnionMember.ts, 13, 57)) +>Circle : Symbol(Circle, Decl(iterableWithNeverAsUnionMember.ts, 13, 57)) +>newValue : Symbol(newValue, Decl(iterableWithNeverAsUnionMember.ts, 17, 51)) +>Circle : Symbol(Circle, Decl(iterableWithNeverAsUnionMember.ts, 13, 57)) + + if (Array.isArray(arg)) { +>Array.isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --)) +>Array : Symbol(Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --) ... and 4 more) +>isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --)) +>arg : Symbol(arg, Decl(iterableWithNeverAsUnionMember.ts, 17, 27)) + + let [value, setValue] = arg; // ok +>value : Symbol(value, Decl(iterableWithNeverAsUnionMember.ts, 19, 9)) +>setValue : Symbol(setValue, Decl(iterableWithNeverAsUnionMember.ts, 19, 15)) +>arg : Symbol(arg, Decl(iterableWithNeverAsUnionMember.ts, 17, 27)) + } +} + +function f1(x: T) { +>f1 : Symbol(f1, Decl(iterableWithNeverAsUnionMember.ts, 21, 1)) +>T : Symbol(T, Decl(iterableWithNeverAsUnionMember.ts, 23, 12)) +>a : Symbol(a, Decl(iterableWithNeverAsUnionMember.ts, 23, 23)) +>a : Symbol(a, Decl(iterableWithNeverAsUnionMember.ts, 23, 38)) +>x : Symbol(x, Decl(iterableWithNeverAsUnionMember.ts, 23, 51)) +>T : Symbol(T, Decl(iterableWithNeverAsUnionMember.ts, 23, 12)) + + let [y] = x; // error +>y : Symbol(y, Decl(iterableWithNeverAsUnionMember.ts, 24, 7)) +>x : Symbol(x, Decl(iterableWithNeverAsUnionMember.ts, 23, 51)) +} + +declare const o2: ({ a: "foo" } & { a: "bar" }) | ({ b: "qwe" } & { b: "rty" }); +>o2 : Symbol(o2, Decl(iterableWithNeverAsUnionMember.ts, 27, 13)) +>a : Symbol(a, Decl(iterableWithNeverAsUnionMember.ts, 27, 20)) +>a : Symbol(a, Decl(iterableWithNeverAsUnionMember.ts, 27, 35)) +>b : Symbol(b, Decl(iterableWithNeverAsUnionMember.ts, 27, 52)) +>b : Symbol(b, Decl(iterableWithNeverAsUnionMember.ts, 27, 67)) + +const [el3] = o2; // error +>el3 : Symbol(el3, Decl(iterableWithNeverAsUnionMember.ts, 28, 7)) +>o2 : Symbol(o2, Decl(iterableWithNeverAsUnionMember.ts, 27, 13)) + diff --git a/tests/baselines/reference/iterableWithNeverAsUnionMember(target=esnext).types b/tests/baselines/reference/iterableWithNeverAsUnionMember(target=esnext).types new file mode 100644 index 0000000000000..b3bb98e8ea674 --- /dev/null +++ b/tests/baselines/reference/iterableWithNeverAsUnionMember(target=esnext).types @@ -0,0 +1,138 @@ +//// [tests/cases/compiler/iterableWithNeverAsUnionMember.ts] //// + +=== iterableWithNeverAsUnionMember.ts === +declare const o1: { a: "foo" } & { a: "bar" }; +>o1 : never +> : ^^^^^ +>a : "foo" +> : ^^^^^ +>a : "bar" +> : ^^^^^ + +const [el1] = o1; // error +>el1 : never +> : ^^^^^ +>o1 : never +> : ^^^^^ + +// https://github.com/microsoft/TypeScript/issues/62462 +declare var x: number[] | ({ t: "a" } & { t: "b" }); +>x : number[] +> : ^^^^^^^^ +>t : "a" +> : ^^^ +>t : "b" +> : ^^^ + +let [el2] = x; // ok +>el2 : number +> : ^^^^^^ +>x : number[] +> : ^^^^^^^^ + +for (const elem of x) { // ok +>elem : number +> : ^^^^^^ +>x : number[] +> : ^^^^^^^^ + + elem.toFixed(); +>elem.toFixed() : string +> : ^^^^^^ +>elem.toFixed : (fractionDigits?: number) => string +> : ^ ^^^ ^^^^^ +>elem : number +> : ^^^^^^ +>toFixed : (fractionDigits?: number) => string +> : ^ ^^^ ^^^^^ +} + +type Shape = +>Shape : Shape +> : ^^^^^ + + | { kind: "circle"; radius: number } +>kind : "circle" +> : ^^^^^^^^ +>radius : number +> : ^^^^^^ + + | { kind: "rectangle"; width: number; height: number }; +>kind : "rectangle" +> : ^^^^^^^^^^^ +>width : number +> : ^^^^^^ +>height : number +> : ^^^^^^ + +type Circle = Shape & { kind: "circle" }; +>Circle : { kind: "circle"; radius: number; } & { kind: "circle"; } +> : ^^^^^^^^ ^^^^^^^^^^ ^^^^^^^^^^^^^^ ^^^ +>kind : "circle" +> : ^^^^^^^^ + +function doStuffWithCircle(arg: Circle | [Circle, (newValue: Circle) => void]) { +>doStuffWithCircle : (arg: Circle | [Circle, (newValue: Circle) => void]) => void +> : ^ ^^ ^^^^^^^^^ +>arg : ({ kind: "circle"; radius: number; } & { kind: "circle"; }) | [{ kind: "circle"; radius: number; } & { kind: "circle"; }, (newValue: Circle) => void] +> : ^^^^^^^^^ ^^^^^^^^^^ ^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^ ^^^^^^^^^^ ^^^^^^^^^^^^^^ ^^^^^^ ^^ ^^^^^ ^ +>newValue : { kind: "circle"; radius: number; } & { kind: "circle"; } +> : ^^^^^^^^ ^^^^^^^^^^ ^^^^^^^^^^^^^^ ^^^ + + if (Array.isArray(arg)) { +>Array.isArray(arg) : boolean +> : ^^^^^^^ +>Array.isArray : (arg: any) => arg is any[] +> : ^ ^^ ^^^^^ +>Array : ArrayConstructor +> : ^^^^^^^^^^^^^^^^ +>isArray : (arg: any) => arg is any[] +> : ^ ^^ ^^^^^ +>arg : ({ kind: "circle"; radius: number; } & { kind: "circle"; }) | [{ kind: "circle"; radius: number; } & { kind: "circle"; }, (newValue: Circle) => void] +> : ^^^^^^^^^ ^^^^^^^^^^ ^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^ ^^^^^^^^^^ ^^^^^^^^^^^^^^ ^^^^^^ ^^ ^^^^^ ^ + + let [value, setValue] = arg; // ok +>value : { kind: "circle"; radius: number; } & { kind: "circle"; } +> : ^^^^^^^^ ^^^^^^^^^^ ^^^^^^^^^^^^^^ ^^^ +>setValue : (newValue: Circle) => void +> : ^ ^^ ^^^^^ +>arg : [{ kind: "circle"; radius: number; } & { kind: "circle"; }, (newValue: Circle) => void] +> : ^^^^^^^^^ ^^^^^^^^^^ ^^^^^^^^^^^^^^ ^^^^^^ ^^ ^^^^^ ^ + } +} + +function f1(x: T) { +>f1 : (x: T) => void +> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^^^^^ +>a : "foo" +> : ^^^^^ +>a : "bar" +> : ^^^^^ +>x : T +> : ^ + + let [y] = x; // error +>y : never +> : ^^^^^ +>x : T +> : ^ +} + +declare const o2: ({ a: "foo" } & { a: "bar" }) | ({ b: "qwe" } & { b: "rty" }); +>o2 : never +> : ^^^^^ +>a : "foo" +> : ^^^^^ +>a : "bar" +> : ^^^^^ +>b : "qwe" +> : ^^^^^ +>b : "rty" +> : ^^^^^ + +const [el3] = o2; // error +>el3 : never +> : ^^^^^ +>o2 : never +> : ^^^^^ + diff --git a/tests/cases/compiler/iterableWithNeverAsUnionMember.ts b/tests/cases/compiler/iterableWithNeverAsUnionMember.ts new file mode 100644 index 0000000000000..2421a222de95d --- /dev/null +++ b/tests/cases/compiler/iterableWithNeverAsUnionMember.ts @@ -0,0 +1,33 @@ +// @strict: true +// @noEmit: true +// @target: es5,esnext + +declare const o1: { a: "foo" } & { a: "bar" }; +const [el1] = o1; // error + +// https://github.com/microsoft/TypeScript/issues/62462 +declare var x: number[] | ({ t: "a" } & { t: "b" }); +let [el2] = x; // ok + +for (const elem of x) { // ok + elem.toFixed(); +} + +type Shape = + | { kind: "circle"; radius: number } + | { kind: "rectangle"; width: number; height: number }; + +type Circle = Shape & { kind: "circle" }; + +function doStuffWithCircle(arg: Circle | [Circle, (newValue: Circle) => void]) { + if (Array.isArray(arg)) { + let [value, setValue] = arg; // ok + } +} + +function f1(x: T) { + let [y] = x; // error +} + +declare const o2: ({ a: "foo" } & { a: "bar" }) | ({ b: "qwe" } & { b: "rty" }); +const [el3] = o2; // error \ No newline at end of file