Enforce strictNullChecks for RHS of empty destructuring assignment

When strictNullChecks is on, check the RHS of the following
destructuring assignments for possible null or undefined:

const {} = ...
const [] = ...
let {} = ...
let [] = ...
({} = ...)
This commit is contained in:
Jack Williams 2018-01-10 01:46:36 +00:00
parent 8bce69e6bd
commit 4acdca5258
6 changed files with 268 additions and 1 deletions

View File

@ -18908,6 +18908,9 @@ namespace ts {
target = (<BinaryExpression>target).left;
}
if (target.kind === SyntaxKind.ObjectLiteralExpression) {
if (strictNullChecks && (<ObjectLiteralExpression>target).properties.length === 0) {
return checkNonNullType(sourceType, target);
}
return checkObjectLiteralAssignment(<ObjectLiteralExpression>target, sourceType);
}
if (target.kind === SyntaxKind.ArrayLiteralExpression) {
@ -21833,7 +21836,11 @@ namespace ts {
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) {
checkTypeAssignableTo(checkExpressionCached(node.initializer), getWidenedTypeForVariableLikeDeclaration(node), node, /*headMessage*/ undefined);
const initializerType = checkExpressionCached(node.initializer);
if (strictNullChecks && node.name.elements.length === 0) {
checkNonNullType(initializerType, node);
}
checkTypeAssignableTo(initializerType, getWidenedTypeForVariableLikeDeclaration(node), node, /*headMessage*/ undefined);
checkParameterInitializer(node);
}
return;

View File

@ -0,0 +1,60 @@
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'.
tests/cases/compiler/strictNullEmptyDestructuring.ts(9,5): error TS2532: Object is possibly 'undefined'.
tests/cases/compiler/strictNullEmptyDestructuring.ts(11,2): error TS2532: Object is possibly 'undefined'.
tests/cases/compiler/strictNullEmptyDestructuring.ts(13,5): error TS2531: Object is possibly 'null'.
tests/cases/compiler/strictNullEmptyDestructuring.ts(15,2): error TS2531: Object is possibly 'null'.
tests/cases/compiler/strictNullEmptyDestructuring.ts(17,5): error TS2532: Object is possibly 'undefined'.
tests/cases/compiler/strictNullEmptyDestructuring.ts(19,2): error TS2532: Object is possibly 'undefined'.
tests/cases/compiler/strictNullEmptyDestructuring.ts(21,5): error TS2533: Object is possibly 'null' or 'undefined'.
tests/cases/compiler/strictNullEmptyDestructuring.ts(23,2): error TS2533: Object is possibly 'null' or 'undefined'.
==== tests/cases/compiler/strictNullEmptyDestructuring.ts (11 errors) ====
// Repro from #20873
let [] = null;
~~
!!! error TS2531: Object is possibly 'null'.
let { } = null;
~~~
!!! error TS2531: Object is possibly 'null'.
({} = null);
~~
!!! error TS2531: Object is possibly 'null'.
let { } = undefined;
~~~
!!! error TS2532: Object is possibly 'undefined'.
({} = undefined);
~~
!!! error TS2532: Object is possibly 'undefined'.
let { } = Math.random() ? {} : null;
~~~
!!! error TS2531: Object is possibly 'null'.
({} = Math.random() ? {} : null);
~~
!!! error TS2531: Object is possibly 'null'.
let { } = Math.random() ? {} : undefined;
~~~
!!! error TS2532: Object is possibly 'undefined'.
({} = Math.random() ? {} : undefined);
~~
!!! error TS2532: Object is possibly 'undefined'.
let { } = Math.random() ? null : undefined;
~~~
!!! error TS2533: Object is possibly 'null' or 'undefined'.
({} = Math.random() ? null : undefined);
~~
!!! error TS2533: Object is possibly 'null' or 'undefined'.

View File

@ -0,0 +1,39 @@
//// [strictNullEmptyDestructuring.ts]
// Repro from #20873
let [] = null;
let { } = null;
({} = null);
let { } = undefined;
({} = undefined);
let { } = Math.random() ? {} : null;
({} = Math.random() ? {} : null);
let { } = Math.random() ? {} : undefined;
({} = Math.random() ? {} : undefined);
let { } = Math.random() ? null : undefined;
({} = Math.random() ? null : undefined);
//// [strictNullEmptyDestructuring.js]
// Repro from #20873
var _a = null;
var _b = null;
(null);
var _c = undefined;
(undefined);
var _d = Math.random() ? {} : null;
(Math.random() ? {} : null);
var _e = Math.random() ? {} : undefined;
(Math.random() ? {} : undefined);
var _f = Math.random() ? null : undefined;
(Math.random() ? null : undefined);

View File

@ -0,0 +1,49 @@
=== tests/cases/compiler/strictNullEmptyDestructuring.ts ===
// Repro from #20873
let [] = null;
let { } = null;
({} = null);
let { } = undefined;
>undefined : Symbol(undefined)
({} = undefined);
>undefined : Symbol(undefined)
let { } = Math.random() ? {} : null;
>Math.random : Symbol(Math.random, Decl(lib.d.ts, --, --))
>Math : Symbol(Math, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
>random : Symbol(Math.random, Decl(lib.d.ts, --, --))
({} = Math.random() ? {} : null);
>Math.random : Symbol(Math.random, Decl(lib.d.ts, --, --))
>Math : Symbol(Math, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
>random : Symbol(Math.random, Decl(lib.d.ts, --, --))
let { } = Math.random() ? {} : undefined;
>Math.random : Symbol(Math.random, Decl(lib.d.ts, --, --))
>Math : Symbol(Math, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
>random : Symbol(Math.random, Decl(lib.d.ts, --, --))
>undefined : Symbol(undefined)
({} = Math.random() ? {} : undefined);
>Math.random : Symbol(Math.random, Decl(lib.d.ts, --, --))
>Math : Symbol(Math, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
>random : Symbol(Math.random, Decl(lib.d.ts, --, --))
>undefined : Symbol(undefined)
let { } = Math.random() ? null : undefined;
>Math.random : Symbol(Math.random, Decl(lib.d.ts, --, --))
>Math : Symbol(Math, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
>random : Symbol(Math.random, Decl(lib.d.ts, --, --))
>undefined : Symbol(undefined)
({} = Math.random() ? null : undefined);
>Math.random : Symbol(Math.random, Decl(lib.d.ts, --, --))
>Math : Symbol(Math, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
>random : Symbol(Math.random, Decl(lib.d.ts, --, --))
>undefined : Symbol(undefined)

View File

@ -0,0 +1,87 @@
=== tests/cases/compiler/strictNullEmptyDestructuring.ts ===
// Repro from #20873
let [] = null;
>null : null
let { } = null;
>null : null
({} = null);
>({} = null) : any
>{} = null : any
>{} : {}
>null : null
let { } = undefined;
>undefined : undefined
({} = undefined);
>({} = undefined) : any
>{} = undefined : any
>{} : {}
>undefined : undefined
let { } = Math.random() ? {} : null;
>Math.random() ? {} : null : {} | null
>Math.random() : number
>Math.random : () => number
>Math : Math
>random : () => number
>{} : {}
>null : null
({} = Math.random() ? {} : null);
>({} = Math.random() ? {} : null) : {}
>{} = Math.random() ? {} : null : {}
>{} : {}
>Math.random() ? {} : null : {} | null
>Math.random() : number
>Math.random : () => number
>Math : Math
>random : () => number
>{} : {}
>null : null
let { } = Math.random() ? {} : undefined;
>Math.random() ? {} : undefined : {} | undefined
>Math.random() : number
>Math.random : () => number
>Math : Math
>random : () => number
>{} : {}
>undefined : undefined
({} = Math.random() ? {} : undefined);
>({} = Math.random() ? {} : undefined) : {}
>{} = Math.random() ? {} : undefined : {}
>{} : {}
>Math.random() ? {} : undefined : {} | undefined
>Math.random() : number
>Math.random : () => number
>Math : Math
>random : () => number
>{} : {}
>undefined : undefined
let { } = Math.random() ? null : undefined;
>Math.random() ? null : undefined : null | undefined
>Math.random() : number
>Math.random : () => number
>Math : Math
>random : () => number
>null : null
>undefined : undefined
({} = Math.random() ? null : undefined);
>({} = Math.random() ? null : undefined) : any
>{} = Math.random() ? null : undefined : any
>{} : {}
>Math.random() ? null : undefined : null | undefined
>Math.random() : number
>Math.random : () => number
>Math : Math
>random : () => number
>null : null
>undefined : undefined

View File

@ -0,0 +1,25 @@
// @strictNullChecks: true
// Repro from #20873
let [] = null;
let { } = null;
({} = null);
let { } = undefined;
({} = undefined);
let { } = Math.random() ? {} : null;
({} = Math.random() ? {} : null);
let { } = Math.random() ? {} : undefined;
({} = Math.random() ? {} : undefined);
let { } = Math.random() ? null : undefined;
({} = Math.random() ? null : undefined);