Skip to content
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

check more case for empty binding patten #25263

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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 []: {} = {}