diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 8f24a76892b..55e994b8aad 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -1721,8 +1721,8 @@ module ts { } } else { - // For an array binding element the specified or inferred type of the parent must be assignable to any[] - if (!isTypeAssignableTo(parentType, anyArrayType)) { + // For an array binding element the specified or inferred type of the parent must be an array-like type + if (!isArrayLikeType(parentType)) { error(pattern, Diagnostics.Type_0_is_not_an_array_type, typeToString(parentType)); return unknownType; } @@ -4190,6 +4190,11 @@ module ts { return type.flags & TypeFlags.Reference && (type).target === globalArrayType; } + function isArrayLikeType(type: Type): boolean { + // A type is array-like if it is not the undefined or null type and if it is assignable to any[] + return !(type.flags & (TypeFlags.Undefined | TypeFlags.Null)) && isTypeAssignableTo(type, anyArrayType); + } + function isTupleLikeType(type: Type): boolean { return !!getPropertyOfType(type, "0"); } @@ -5466,7 +5471,7 @@ module ts { function checkSpreadElementExpression(node: SpreadElementExpression, contextualMapper?: TypeMapper): Type { var type = checkExpressionCached(node.expression, contextualMapper); - if (!isTypeAssignableTo(type, anyArrayType)) { + if (!isArrayLikeType(type)) { error(node.expression, Diagnostics.Type_0_is_not_an_array_type, typeToString(type)); return unknownType; } @@ -7074,7 +7079,7 @@ module ts { function checkArrayLiteralAssignment(node: ArrayLiteralExpression, sourceType: Type, contextualMapper?: TypeMapper): Type { // TODOO(andersh): Allow iterable source type in ES6 - if (!isTypeAssignableTo(sourceType, anyArrayType)) { + if (!isArrayLikeType(sourceType)) { error(node, Diagnostics.Type_0_is_not_an_array_type, typeToString(sourceType)); return sourceType; } diff --git a/tests/baselines/reference/restElementWithNullInitializer.errors.txt b/tests/baselines/reference/restElementWithNullInitializer.errors.txt new file mode 100644 index 00000000000..7beb7b9a642 --- /dev/null +++ b/tests/baselines/reference/restElementWithNullInitializer.errors.txt @@ -0,0 +1,24 @@ +tests/cases/conformance/es6/destructuring/restElementWithNullInitializer.ts(1,15): error TS2461: Type 'null' is not an array type. +tests/cases/conformance/es6/destructuring/restElementWithNullInitializer.ts(4,15): error TS2461: Type 'undefined' is not an array type. +tests/cases/conformance/es6/destructuring/restElementWithNullInitializer.ts(7,15): error TS2461: Type '{ [x: number]: undefined; }' is not an array type. + + +==== tests/cases/conformance/es6/destructuring/restElementWithNullInitializer.ts (3 errors) ==== + function foo1([...r] = null) { + ~~~~~~ +!!! error TS2461: Type 'null' is not an array type. + } + + function foo2([...r] = undefined) { + ~~~~~~ +!!! error TS2461: Type 'undefined' is not an array type. + } + + function foo3([...r] = {}) { + ~~~~~~ +!!! error TS2461: Type '{ [x: number]: undefined; }' is not an array type. + } + + function foo4([...r] = []) { + } + \ No newline at end of file diff --git a/tests/baselines/reference/restElementWithNullInitializer.js b/tests/baselines/reference/restElementWithNullInitializer.js new file mode 100644 index 00000000000..9f326602fb8 --- /dev/null +++ b/tests/baselines/reference/restElementWithNullInitializer.js @@ -0,0 +1,27 @@ +//// [restElementWithNullInitializer.ts] +function foo1([...r] = null) { +} + +function foo2([...r] = undefined) { +} + +function foo3([...r] = {}) { +} + +function foo4([...r] = []) { +} + + +//// [restElementWithNullInitializer.js] +function foo1(_a) { + var _b = _a === void 0 ? null : _a, r = _b.slice(0); +} +function foo2(_a) { + var _b = _a === void 0 ? undefined : _a, r = _b.slice(0); +} +function foo3(_a) { + var _b = _a === void 0 ? {} : _a, r = _b.slice(0); +} +function foo4(_a) { + var _b = _a === void 0 ? [] : _a, r = _b.slice(0); +} diff --git a/tests/cases/conformance/es6/destructuring/restElementWithNullInitializer.ts b/tests/cases/conformance/es6/destructuring/restElementWithNullInitializer.ts new file mode 100644 index 00000000000..1b03c533e7d --- /dev/null +++ b/tests/cases/conformance/es6/destructuring/restElementWithNullInitializer.ts @@ -0,0 +1,11 @@ +function foo1([...r] = null) { +} + +function foo2([...r] = undefined) { +} + +function foo3([...r] = {}) { +} + +function foo4([...r] = []) { +}