mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-06 02:33:53 -06:00
* Cherry-pick PR #47927 into release-4.6 Component commits: c4aa31b67f early return if pattern type is never * Update LKG Co-authored-by: Gabriela Araujo Britto <gabrielaa@microsoft.com> Co-authored-by: typescript-bot <typescript@microsoft.com>
This commit is contained in:
parent
f4fe064b38
commit
78ee4cacaf
@ -58514,6 +58514,9 @@ var ts;
|
||||
if (parentType && parentType.flags & 1048576 && !(parent.kind === 163 && isSymbolAssigned(symbol))) {
|
||||
var pattern = declaration.parent;
|
||||
var narrowedType = getFlowTypeOfReference(pattern, parentType, parentType, undefined, location.flowNode);
|
||||
if (narrowedType.flags & 131072) {
|
||||
return neverType;
|
||||
}
|
||||
return getBindingElementTypeFromParentType(declaration, narrowedType);
|
||||
}
|
||||
}
|
||||
|
||||
@ -70031,6 +70031,9 @@ var ts;
|
||||
if (parentType && parentType.flags & 1048576 /* Union */ && !(parent.kind === 163 /* Parameter */ && isSymbolAssigned(symbol))) {
|
||||
var pattern = declaration.parent;
|
||||
var narrowedType = getFlowTypeOfReference(pattern, parentType, parentType, /*flowContainer*/ undefined, location.flowNode);
|
||||
if (narrowedType.flags & 131072 /* Never */) {
|
||||
return neverType;
|
||||
}
|
||||
return getBindingElementTypeFromParentType(declaration, narrowedType);
|
||||
}
|
||||
}
|
||||
|
||||
@ -70225,6 +70225,9 @@ var ts;
|
||||
if (parentType && parentType.flags & 1048576 /* Union */ && !(parent.kind === 163 /* Parameter */ && isSymbolAssigned(symbol))) {
|
||||
var pattern = declaration.parent;
|
||||
var narrowedType = getFlowTypeOfReference(pattern, parentType, parentType, /*flowContainer*/ undefined, location.flowNode);
|
||||
if (narrowedType.flags & 131072 /* Never */) {
|
||||
return neverType;
|
||||
}
|
||||
return getBindingElementTypeFromParentType(declaration, narrowedType);
|
||||
}
|
||||
}
|
||||
|
||||
@ -70225,6 +70225,9 @@ var ts;
|
||||
if (parentType && parentType.flags & 1048576 /* Union */ && !(parent.kind === 163 /* Parameter */ && isSymbolAssigned(symbol))) {
|
||||
var pattern = declaration.parent;
|
||||
var narrowedType = getFlowTypeOfReference(pattern, parentType, parentType, /*flowContainer*/ undefined, location.flowNode);
|
||||
if (narrowedType.flags & 131072 /* Never */) {
|
||||
return neverType;
|
||||
}
|
||||
return getBindingElementTypeFromParentType(declaration, narrowedType);
|
||||
}
|
||||
}
|
||||
|
||||
@ -70225,6 +70225,9 @@ var ts;
|
||||
if (parentType && parentType.flags & 1048576 /* Union */ && !(parent.kind === 163 /* Parameter */ && isSymbolAssigned(symbol))) {
|
||||
var pattern = declaration.parent;
|
||||
var narrowedType = getFlowTypeOfReference(pattern, parentType, parentType, /*flowContainer*/ undefined, location.flowNode);
|
||||
if (narrowedType.flags & 131072 /* Never */) {
|
||||
return neverType;
|
||||
}
|
||||
return getBindingElementTypeFromParentType(declaration, narrowedType);
|
||||
}
|
||||
}
|
||||
|
||||
@ -70020,6 +70020,9 @@ var ts;
|
||||
if (parentType && parentType.flags & 1048576 /* Union */ && !(parent.kind === 163 /* Parameter */ && isSymbolAssigned(symbol))) {
|
||||
var pattern = declaration.parent;
|
||||
var narrowedType = getFlowTypeOfReference(pattern, parentType, parentType, /*flowContainer*/ undefined, location.flowNode);
|
||||
if (narrowedType.flags & 131072 /* Never */) {
|
||||
return neverType;
|
||||
}
|
||||
return getBindingElementTypeFromParentType(declaration, narrowedType);
|
||||
}
|
||||
}
|
||||
|
||||
@ -25127,6 +25127,9 @@ namespace ts {
|
||||
if (parentType && parentType.flags & TypeFlags.Union && !(parent.kind === SyntaxKind.Parameter && isSymbolAssigned(symbol))) {
|
||||
const pattern = declaration.parent;
|
||||
const narrowedType = getFlowTypeOfReference(pattern, parentType, parentType, /*flowContainer*/ undefined, location.flowNode);
|
||||
if (narrowedType.flags & TypeFlags.Never) {
|
||||
return neverType;
|
||||
}
|
||||
return getBindingElementTypeFromParentType(declaration, narrowedType);
|
||||
}
|
||||
}
|
||||
|
||||
47
tests/baselines/reference/arrayDestructuringInSwitch1.js
Normal file
47
tests/baselines/reference/arrayDestructuringInSwitch1.js
Normal file
@ -0,0 +1,47 @@
|
||||
//// [arrayDestructuringInSwitch1.ts]
|
||||
export type Expression = BooleanLogicExpression | 'true' | 'false';
|
||||
export type BooleanLogicExpression = ['and', ...Expression[]] | ['not', Expression];
|
||||
|
||||
export function evaluate(expression: Expression): boolean {
|
||||
if (Array.isArray(expression)) {
|
||||
const [operator, ...operands] = expression;
|
||||
switch (operator) {
|
||||
case 'and': {
|
||||
return operands.every((child) => evaluate(child));
|
||||
}
|
||||
case 'not': {
|
||||
return !evaluate(operands[0]);
|
||||
}
|
||||
default: {
|
||||
throw new Error(`${operator} is not a supported operator`);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return expression === 'true';
|
||||
}
|
||||
}
|
||||
|
||||
//// [arrayDestructuringInSwitch1.js]
|
||||
"use strict";
|
||||
exports.__esModule = true;
|
||||
exports.evaluate = void 0;
|
||||
function evaluate(expression) {
|
||||
if (Array.isArray(expression)) {
|
||||
var operator = expression[0], operands = expression.slice(1);
|
||||
switch (operator) {
|
||||
case 'and': {
|
||||
return operands.every(function (child) { return evaluate(child); });
|
||||
}
|
||||
case 'not': {
|
||||
return !evaluate(operands[0]);
|
||||
}
|
||||
default: {
|
||||
throw new Error("".concat(operator, " is not a supported operator"));
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
return expression === 'true';
|
||||
}
|
||||
}
|
||||
exports.evaluate = evaluate;
|
||||
@ -0,0 +1,55 @@
|
||||
=== tests/cases/compiler/arrayDestructuringInSwitch1.ts ===
|
||||
export type Expression = BooleanLogicExpression | 'true' | 'false';
|
||||
>Expression : Symbol(Expression, Decl(arrayDestructuringInSwitch1.ts, 0, 0))
|
||||
>BooleanLogicExpression : Symbol(BooleanLogicExpression, Decl(arrayDestructuringInSwitch1.ts, 0, 67))
|
||||
|
||||
export type BooleanLogicExpression = ['and', ...Expression[]] | ['not', Expression];
|
||||
>BooleanLogicExpression : Symbol(BooleanLogicExpression, Decl(arrayDestructuringInSwitch1.ts, 0, 67))
|
||||
>Expression : Symbol(Expression, Decl(arrayDestructuringInSwitch1.ts, 0, 0))
|
||||
>Expression : Symbol(Expression, Decl(arrayDestructuringInSwitch1.ts, 0, 0))
|
||||
|
||||
export function evaluate(expression: Expression): boolean {
|
||||
>evaluate : Symbol(evaluate, Decl(arrayDestructuringInSwitch1.ts, 1, 84))
|
||||
>expression : Symbol(expression, Decl(arrayDestructuringInSwitch1.ts, 3, 25))
|
||||
>Expression : Symbol(Expression, Decl(arrayDestructuringInSwitch1.ts, 0, 0))
|
||||
|
||||
if (Array.isArray(expression)) {
|
||||
>Array.isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --))
|
||||
>Array : Symbol(Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
|
||||
>isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --))
|
||||
>expression : Symbol(expression, Decl(arrayDestructuringInSwitch1.ts, 3, 25))
|
||||
|
||||
const [operator, ...operands] = expression;
|
||||
>operator : Symbol(operator, Decl(arrayDestructuringInSwitch1.ts, 5, 11))
|
||||
>operands : Symbol(operands, Decl(arrayDestructuringInSwitch1.ts, 5, 20))
|
||||
>expression : Symbol(expression, Decl(arrayDestructuringInSwitch1.ts, 3, 25))
|
||||
|
||||
switch (operator) {
|
||||
>operator : Symbol(operator, Decl(arrayDestructuringInSwitch1.ts, 5, 11))
|
||||
|
||||
case 'and': {
|
||||
return operands.every((child) => evaluate(child));
|
||||
>operands.every : Symbol(Array.every, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
|
||||
>operands : Symbol(operands, Decl(arrayDestructuringInSwitch1.ts, 5, 20))
|
||||
>every : Symbol(Array.every, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
|
||||
>child : Symbol(child, Decl(arrayDestructuringInSwitch1.ts, 8, 31))
|
||||
>evaluate : Symbol(evaluate, Decl(arrayDestructuringInSwitch1.ts, 1, 84))
|
||||
>child : Symbol(child, Decl(arrayDestructuringInSwitch1.ts, 8, 31))
|
||||
}
|
||||
case 'not': {
|
||||
return !evaluate(operands[0]);
|
||||
>evaluate : Symbol(evaluate, Decl(arrayDestructuringInSwitch1.ts, 1, 84))
|
||||
>operands : Symbol(operands, Decl(arrayDestructuringInSwitch1.ts, 5, 20))
|
||||
>0 : Symbol(0)
|
||||
}
|
||||
default: {
|
||||
throw new Error(`${operator} is not a supported operator`);
|
||||
>Error : Symbol(Error, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
|
||||
>operator : Symbol(operator, Decl(arrayDestructuringInSwitch1.ts, 5, 11))
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return expression === 'true';
|
||||
>expression : Symbol(expression, Decl(arrayDestructuringInSwitch1.ts, 3, 25))
|
||||
}
|
||||
}
|
||||
66
tests/baselines/reference/arrayDestructuringInSwitch1.types
Normal file
66
tests/baselines/reference/arrayDestructuringInSwitch1.types
Normal file
@ -0,0 +1,66 @@
|
||||
=== tests/cases/compiler/arrayDestructuringInSwitch1.ts ===
|
||||
export type Expression = BooleanLogicExpression | 'true' | 'false';
|
||||
>Expression : Expression
|
||||
|
||||
export type BooleanLogicExpression = ['and', ...Expression[]] | ['not', Expression];
|
||||
>BooleanLogicExpression : BooleanLogicExpression
|
||||
|
||||
export function evaluate(expression: Expression): boolean {
|
||||
>evaluate : (expression: Expression) => boolean
|
||||
>expression : Expression
|
||||
|
||||
if (Array.isArray(expression)) {
|
||||
>Array.isArray(expression) : boolean
|
||||
>Array.isArray : (arg: any) => arg is any[]
|
||||
>Array : ArrayConstructor
|
||||
>isArray : (arg: any) => arg is any[]
|
||||
>expression : Expression
|
||||
|
||||
const [operator, ...operands] = expression;
|
||||
>operator : "and" | "not"
|
||||
>operands : Expression[] | [Expression]
|
||||
>expression : BooleanLogicExpression
|
||||
|
||||
switch (operator) {
|
||||
>operator : "and" | "not"
|
||||
|
||||
case 'and': {
|
||||
>'and' : "and"
|
||||
|
||||
return operands.every((child) => evaluate(child));
|
||||
>operands.every((child) => evaluate(child)) : boolean
|
||||
>operands.every : { <S extends Expression>(predicate: (value: Expression, index: number, array: Expression[]) => value is S, thisArg?: any): this is S[]; (predicate: (value: Expression, index: number, array: Expression[]) => unknown, thisArg?: any): boolean; } | { <S extends Expression>(predicate: (value: Expression, index: number, array: Expression[]) => value is S, thisArg?: any): this is S[]; (predicate: (value: Expression, index: number, array: Expression[]) => unknown, thisArg?: any): boolean; }
|
||||
>operands : Expression[] | [Expression]
|
||||
>every : { <S extends Expression>(predicate: (value: Expression, index: number, array: Expression[]) => value is S, thisArg?: any): this is S[]; (predicate: (value: Expression, index: number, array: Expression[]) => unknown, thisArg?: any): boolean; } | { <S extends Expression>(predicate: (value: Expression, index: number, array: Expression[]) => value is S, thisArg?: any): this is S[]; (predicate: (value: Expression, index: number, array: Expression[]) => unknown, thisArg?: any): boolean; }
|
||||
>(child) => evaluate(child) : (child: Expression) => boolean
|
||||
>child : Expression
|
||||
>evaluate(child) : boolean
|
||||
>evaluate : (expression: Expression) => boolean
|
||||
>child : Expression
|
||||
}
|
||||
case 'not': {
|
||||
>'not' : "not"
|
||||
|
||||
return !evaluate(operands[0]);
|
||||
>!evaluate(operands[0]) : boolean
|
||||
>evaluate(operands[0]) : boolean
|
||||
>evaluate : (expression: Expression) => boolean
|
||||
>operands[0] : Expression
|
||||
>operands : Expression[] | [Expression]
|
||||
>0 : 0
|
||||
}
|
||||
default: {
|
||||
throw new Error(`${operator} is not a supported operator`);
|
||||
>new Error(`${operator} is not a supported operator`) : Error
|
||||
>Error : ErrorConstructor
|
||||
>`${operator} is not a supported operator` : string
|
||||
>operator : never
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return expression === 'true';
|
||||
>expression === 'true' : boolean
|
||||
>expression : "true" | "false"
|
||||
>'true' : "true"
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,20 @@
|
||||
tests/cases/compiler/arrayDestructuringInSwitch2.ts(11,13): error TS2488: Type 'never' must have a '[Symbol.iterator]()' method that returns an iterator.
|
||||
|
||||
|
||||
==== tests/cases/compiler/arrayDestructuringInSwitch2.ts (1 errors) ====
|
||||
type X = { kind: "a", a: [1] } | { kind: "b", a: [] }
|
||||
|
||||
function foo(x: X): 1 {
|
||||
const { kind, a } = x;
|
||||
switch (kind) {
|
||||
case "a":
|
||||
return a[0];
|
||||
case "b":
|
||||
return 1;
|
||||
default:
|
||||
const [n] = a;
|
||||
~~~
|
||||
!!! error TS2488: Type 'never' must have a '[Symbol.iterator]()' method that returns an iterator.
|
||||
return a;
|
||||
}
|
||||
}
|
||||
29
tests/baselines/reference/arrayDestructuringInSwitch2.js
Normal file
29
tests/baselines/reference/arrayDestructuringInSwitch2.js
Normal file
@ -0,0 +1,29 @@
|
||||
//// [arrayDestructuringInSwitch2.ts]
|
||||
type X = { kind: "a", a: [1] } | { kind: "b", a: [] }
|
||||
|
||||
function foo(x: X): 1 {
|
||||
const { kind, a } = x;
|
||||
switch (kind) {
|
||||
case "a":
|
||||
return a[0];
|
||||
case "b":
|
||||
return 1;
|
||||
default:
|
||||
const [n] = a;
|
||||
return a;
|
||||
}
|
||||
}
|
||||
|
||||
//// [arrayDestructuringInSwitch2.js]
|
||||
function foo(x) {
|
||||
var kind = x.kind, a = x.a;
|
||||
switch (kind) {
|
||||
case "a":
|
||||
return a[0];
|
||||
case "b":
|
||||
return 1;
|
||||
default:
|
||||
var n = a[0];
|
||||
return a;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,37 @@
|
||||
=== tests/cases/compiler/arrayDestructuringInSwitch2.ts ===
|
||||
type X = { kind: "a", a: [1] } | { kind: "b", a: [] }
|
||||
>X : Symbol(X, Decl(arrayDestructuringInSwitch2.ts, 0, 0))
|
||||
>kind : Symbol(kind, Decl(arrayDestructuringInSwitch2.ts, 0, 10))
|
||||
>a : Symbol(a, Decl(arrayDestructuringInSwitch2.ts, 0, 21))
|
||||
>kind : Symbol(kind, Decl(arrayDestructuringInSwitch2.ts, 0, 34))
|
||||
>a : Symbol(a, Decl(arrayDestructuringInSwitch2.ts, 0, 45))
|
||||
|
||||
function foo(x: X): 1 {
|
||||
>foo : Symbol(foo, Decl(arrayDestructuringInSwitch2.ts, 0, 53))
|
||||
>x : Symbol(x, Decl(arrayDestructuringInSwitch2.ts, 2, 13))
|
||||
>X : Symbol(X, Decl(arrayDestructuringInSwitch2.ts, 0, 0))
|
||||
|
||||
const { kind, a } = x;
|
||||
>kind : Symbol(kind, Decl(arrayDestructuringInSwitch2.ts, 3, 9))
|
||||
>a : Symbol(a, Decl(arrayDestructuringInSwitch2.ts, 3, 15))
|
||||
>x : Symbol(x, Decl(arrayDestructuringInSwitch2.ts, 2, 13))
|
||||
|
||||
switch (kind) {
|
||||
>kind : Symbol(kind, Decl(arrayDestructuringInSwitch2.ts, 3, 9))
|
||||
|
||||
case "a":
|
||||
return a[0];
|
||||
>a : Symbol(a, Decl(arrayDestructuringInSwitch2.ts, 3, 15))
|
||||
>0 : Symbol(0)
|
||||
|
||||
case "b":
|
||||
return 1;
|
||||
default:
|
||||
const [n] = a;
|
||||
>n : Symbol(n, Decl(arrayDestructuringInSwitch2.ts, 10, 13))
|
||||
>a : Symbol(a, Decl(arrayDestructuringInSwitch2.ts, 3, 15))
|
||||
|
||||
return a;
|
||||
>a : Symbol(a, Decl(arrayDestructuringInSwitch2.ts, 3, 15))
|
||||
}
|
||||
}
|
||||
43
tests/baselines/reference/arrayDestructuringInSwitch2.types
Normal file
43
tests/baselines/reference/arrayDestructuringInSwitch2.types
Normal file
@ -0,0 +1,43 @@
|
||||
=== tests/cases/compiler/arrayDestructuringInSwitch2.ts ===
|
||||
type X = { kind: "a", a: [1] } | { kind: "b", a: [] }
|
||||
>X : X
|
||||
>kind : "a"
|
||||
>a : [1]
|
||||
>kind : "b"
|
||||
>a : []
|
||||
|
||||
function foo(x: X): 1 {
|
||||
>foo : (x: X) => 1
|
||||
>x : X
|
||||
|
||||
const { kind, a } = x;
|
||||
>kind : "a" | "b"
|
||||
>a : [1] | []
|
||||
>x : X
|
||||
|
||||
switch (kind) {
|
||||
>kind : "a" | "b"
|
||||
|
||||
case "a":
|
||||
>"a" : "a"
|
||||
|
||||
return a[0];
|
||||
>a[0] : 1
|
||||
>a : [1]
|
||||
>0 : 0
|
||||
|
||||
case "b":
|
||||
>"b" : "b"
|
||||
|
||||
return 1;
|
||||
>1 : 1
|
||||
|
||||
default:
|
||||
const [n] = a;
|
||||
>n : never
|
||||
>a : never
|
||||
|
||||
return a;
|
||||
>a : never
|
||||
}
|
||||
}
|
||||
21
tests/cases/compiler/arrayDestructuringInSwitch1.ts
Normal file
21
tests/cases/compiler/arrayDestructuringInSwitch1.ts
Normal file
@ -0,0 +1,21 @@
|
||||
export type Expression = BooleanLogicExpression | 'true' | 'false';
|
||||
export type BooleanLogicExpression = ['and', ...Expression[]] | ['not', Expression];
|
||||
|
||||
export function evaluate(expression: Expression): boolean {
|
||||
if (Array.isArray(expression)) {
|
||||
const [operator, ...operands] = expression;
|
||||
switch (operator) {
|
||||
case 'and': {
|
||||
return operands.every((child) => evaluate(child));
|
||||
}
|
||||
case 'not': {
|
||||
return !evaluate(operands[0]);
|
||||
}
|
||||
default: {
|
||||
throw new Error(`${operator} is not a supported operator`);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return expression === 'true';
|
||||
}
|
||||
}
|
||||
14
tests/cases/compiler/arrayDestructuringInSwitch2.ts
Normal file
14
tests/cases/compiler/arrayDestructuringInSwitch2.ts
Normal file
@ -0,0 +1,14 @@
|
||||
type X = { kind: "a", a: [1] } | { kind: "b", a: [] }
|
||||
|
||||
function foo(x: X): 1 {
|
||||
const { kind, a } = x;
|
||||
switch (kind) {
|
||||
case "a":
|
||||
return a[0];
|
||||
case "b":
|
||||
return 1;
|
||||
default:
|
||||
const [n] = a;
|
||||
return a;
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user