Skip to content

Commit

Permalink
check more case for empty binding patten (#25263)
Browse files Browse the repository at this point in the history
* check more case for empty binding patten

* refactor binding pattern checking  getWidenedType

* fix spelling

* fix merge and rebase
  • Loading branch information
Kingwl authored and RyanCavanaugh committed Apr 26, 2019
1 parent d934401 commit 454b428
Show file tree
Hide file tree
Showing 7 changed files with 181 additions and 8 deletions.
28 changes: 21 additions & 7 deletions src/compiler/checker.ts
Expand Up @@ -26462,14 +26462,28 @@ namespace ts {
}
// For a binding pattern, validate the initializer and exit
if (isBindingPattern(node.name)) {
// Don't validate for-in initializer as it is already an error
if (node.initializer && node.parent.parent.kind !== SyntaxKind.ForInStatement) {
const initializerType = checkExpressionCached(node.initializer);
if (strictNullChecks && node.name.elements.length === 0) {
checkNonNullNonVoidType(initializerType, node);
const needCheckInitializer = node.initializer && node.parent.parent.kind !== SyntaxKind.ForInStatement;
const needCheckWidenedType = node.name.elements.length === 0;
if (needCheckInitializer || needCheckWidenedType) {
// Don't validate for-in initializer as it is already an error
const widenedType = getWidenedTypeForVariableLikeDeclaration(node);
if (needCheckInitializer) {
const initializerType = checkExpressionCached(node.initializer!);
if (strictNullChecks && needCheckWidenedType) {
checkNonNullNonVoidType(initializerType, node);
}
else {
checkTypeAssignableToAndOptionallyElaborate(initializerType, getWidenedTypeForVariableLikeDeclaration(node), node, node.initializer);
}
}
else {
checkTypeAssignableToAndOptionallyElaborate(initializerType, getWidenedTypeForVariableLikeDeclaration(node), node, node.initializer);
// check the binding pattern with empty elements
if (needCheckWidenedType) {
if (isArrayBindingPattern(node.name)) {
checkIteratedTypeOrElementType(widenedType, node, /* allowStringInput */ false, /* allowAsyncIterables */ false);
}
else if (strictNullChecks) {
checkNonNullNonVoidType(widenedType, node);
}
}
}
return;
Expand Down
@@ -0,0 +1,43 @@
tests/cases/conformance/es6/destructuring/destructuringAssignabilityCheck.ts(1,7): error TS2461: Type '{}' is not an array type.
tests/cases/conformance/es6/destructuring/destructuringAssignabilityCheck.ts(2,7): error TS2532: Object is possibly 'undefined'.
tests/cases/conformance/es6/destructuring/destructuringAssignabilityCheck.ts(3,3): error TS2461: Type '{}' is not an array type.
tests/cases/conformance/es6/destructuring/destructuringAssignabilityCheck.ts(4,3): error TS2532: Object is possibly 'undefined'.
tests/cases/conformance/es6/destructuring/destructuringAssignabilityCheck.ts(6,14): error TS2532: Object is possibly 'undefined'.
tests/cases/conformance/es6/destructuring/destructuringAssignabilityCheck.ts(9,14): error TS2461: Type '{}' is not an array type.
tests/cases/conformance/es6/destructuring/destructuringAssignabilityCheck.ts(13,7): error TS2532: Object is possibly 'undefined'.
tests/cases/conformance/es6/destructuring/destructuringAssignabilityCheck.ts(15,7): error TS2461: Type '{}' is not an array type.


==== tests/cases/conformance/es6/destructuring/destructuringAssignabilityCheck.ts (8 errors) ====
const [] = {}; // should be error
~~
!!! error TS2461: Type '{}' is not an array type.
const {} = undefined; // error correctly
~~
!!! error TS2532: Object is possibly 'undefined'.
(([]) => 0)({}); // should be error
~~
!!! error TS2461: Type '{}' is not an array type.
(({}) => 0)(undefined); // should be error
~~
!!! error TS2532: Object is possibly 'undefined'.

function foo({}: undefined) {
~~~~~~~~~~~~~
!!! error TS2532: Object is possibly 'undefined'.
return 0
}
function bar([]: {}) {
~~~~~~
!!! error TS2461: Type '{}' is not an array type.
return 0
}

const { }: undefined = 1
~~~
!!! error TS2532: Object is possibly 'undefined'.

const []: {} = {}
~~
!!! error TS2461: Type '{}' is not an array type.

32 changes: 32 additions & 0 deletions tests/baselines/reference/destructuringAssignabilityCheck.js
@@ -0,0 +1,32 @@
//// [destructuringAssignabilityCheck.ts]
const [] = {}; // should be error
const {} = undefined; // error correctly
(([]) => 0)({}); // should be error
(({}) => 0)(undefined); // should be error

function foo({}: undefined) {
return 0
}
function bar([]: {}) {
return 0
}

const { }: undefined = 1

const []: {} = {}


//// [destructuringAssignabilityCheck.js]
"use strict";
var _a = {}; // should be error
var _b = undefined; // error correctly
(function (_a) { return 0; })({}); // should be error
(function (_a) { return 0; })(undefined); // should be error
function foo(_a) {
return 0;
}
function bar(_a) {
return 0;
}
var _c = 1;
var _d = {};
24 changes: 24 additions & 0 deletions tests/baselines/reference/destructuringAssignabilityCheck.symbols
@@ -0,0 +1,24 @@
=== tests/cases/conformance/es6/destructuring/destructuringAssignabilityCheck.ts ===
const [] = {}; // should be error
const {} = undefined; // error correctly
>undefined : Symbol(undefined)

(([]) => 0)({}); // should be error
(({}) => 0)(undefined); // should be error
>undefined : Symbol(undefined)

function foo({}: undefined) {
>foo : Symbol(foo, Decl(destructuringAssignabilityCheck.ts, 3, 23))

return 0
}
function bar([]: {}) {
>bar : Symbol(bar, Decl(destructuringAssignabilityCheck.ts, 7, 1))

return 0
}

const { }: undefined = 1

const []: {} = {}

40 changes: 40 additions & 0 deletions tests/baselines/reference/destructuringAssignabilityCheck.types
@@ -0,0 +1,40 @@
=== tests/cases/conformance/es6/destructuring/destructuringAssignabilityCheck.ts ===
const [] = {}; // should be error
>{} : {}

const {} = undefined; // error correctly
>undefined : undefined

(([]) => 0)({}); // should be error
>(([]) => 0)({}) : number
>(([]) => 0) : ([]: {}) => number
>([]) => 0 : ([]: {}) => number
>0 : 0
>{} : {}

(({}) => 0)(undefined); // should be error
>(({}) => 0)(undefined) : number
>(({}) => 0) : ({}: undefined) => number
>({}) => 0 : ({}: undefined) => number
>0 : 0
>undefined : undefined

function foo({}: undefined) {
>foo : ({}: undefined) => number

return 0
>0 : 0
}
function bar([]: {}) {
>bar : ([]: {}) => number

return 0
>0 : 0
}

const { }: undefined = 1
>1 : 1

const []: {} = {}
>{} : {}

@@ -1,3 +1,4 @@
tests/cases/compiler/strictNullEmptyDestructuring.ts(3,5): error TS2461: Type 'null' is not an array type.
tests/cases/compiler/strictNullEmptyDestructuring.ts(3,5): error TS2531: Object is possibly 'null'.
tests/cases/compiler/strictNullEmptyDestructuring.ts(5,5): error TS2531: Object is possibly 'null'.
tests/cases/compiler/strictNullEmptyDestructuring.ts(7,2): error TS2531: Object is possibly 'null'.
Expand All @@ -11,11 +12,13 @@ tests/cases/compiler/strictNullEmptyDestructuring.ts(21,5): error TS2533: Object
tests/cases/compiler/strictNullEmptyDestructuring.ts(23,2): error TS2533: Object is possibly 'null' or 'undefined'.


==== tests/cases/compiler/strictNullEmptyDestructuring.ts (11 errors) ====
==== tests/cases/compiler/strictNullEmptyDestructuring.ts (12 errors) ====
// Repro from #20873

let [] = null;
~~
!!! error TS2461: Type 'null' is not an array type.
~~
!!! error TS2531: Object is possibly 'null'.

let { } = null;
Expand Down
@@ -0,0 +1,17 @@
// @strict: true

const [] = {}; // should be error
const {} = undefined; // error correctly
(([]) => 0)({}); // should be error
(({}) => 0)(undefined); // should be error

function foo({}: undefined) {
return 0
}
function bar([]: {}) {
return 0
}

const { }: undefined = 1

const []: {} = {}

0 comments on commit 454b428

Please sign in to comment.