From 24ddbe4b60a2d755a604a5f485206eb704e4599b Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Thu, 9 Feb 2017 14:55:07 -0800 Subject: [PATCH] Widen after sub-type-reduction took place --- src/compiler/checker.ts | 6 ++--- .../jsFileClassPropertyType3.errors.txt | 22 +++++++++++++++++++ .../reference/multipleDeclarations.types | 2 +- .../compiler/jsFileClassPropertyType3.ts | 18 +++++++++++++++ 4 files changed, 44 insertions(+), 4 deletions(-) create mode 100644 tests/baselines/reference/jsFileClassPropertyType3.errors.txt create mode 100644 tests/cases/compiler/jsFileClassPropertyType3.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 10c5f5422e3..831126adfa1 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -3378,7 +3378,7 @@ namespace ts { } // Return the inferred type for a variable, parameter, or property declaration - function getWidenedTypeForJSSpecialPropertyDeclaration(declaration: Declaration): Type { + function getTypeForJSSpecialPropertyDeclaration(declaration: Declaration): Type { const expression = declaration.kind === SyntaxKind.BinaryExpression ? declaration : declaration.kind === SyntaxKind.PropertyAccessExpression ? getAncestor(declaration, SyntaxKind.BinaryExpression) : undefined; @@ -3395,7 +3395,7 @@ namespace ts { } } - return getWidenedType(getWidenedLiteralType(checkExpressionCached(expression.right))); + return getWidenedLiteralType(checkExpressionCached(expression.right)); } // Return the type implied by a binding pattern element. This is the type of the initializer of the element if @@ -3552,7 +3552,7 @@ namespace ts { // * className.prototype.method = expr if (declaration.kind === SyntaxKind.BinaryExpression || declaration.kind === SyntaxKind.PropertyAccessExpression && declaration.parent.kind === SyntaxKind.BinaryExpression) { - type = getUnionType(map(symbol.declarations, getWidenedTypeForJSSpecialPropertyDeclaration), /*subtypeReduction*/ true); + type = getWidenedType(getUnionType(map(symbol.declarations, getTypeForJSSpecialPropertyDeclaration), /*subtypeReduction*/ true)); } else { type = getWidenedTypeForVariableLikeDeclaration(declaration, /*reportErrors*/ true); diff --git a/tests/baselines/reference/jsFileClassPropertyType3.errors.txt b/tests/baselines/reference/jsFileClassPropertyType3.errors.txt new file mode 100644 index 00000000000..bf225095b01 --- /dev/null +++ b/tests/baselines/reference/jsFileClassPropertyType3.errors.txt @@ -0,0 +1,22 @@ +tests/cases/compiler/bar.ts(2,1): error TS2322: Type '"string"' is not assignable to type 'number'. + + +==== tests/cases/compiler/foo.js (0 errors) ==== + + class C { + constructor() { + if (cond) { + this.p = null; + } + else { + this.p = 0; + } + } + } + +==== tests/cases/compiler/bar.ts (1 errors) ==== + + (new C()).p = "string"; // Error + ~~~~~~~~~~~ +!!! error TS2322: Type '"string"' is not assignable to type 'number'. + \ No newline at end of file diff --git a/tests/baselines/reference/multipleDeclarations.types b/tests/baselines/reference/multipleDeclarations.types index c11bd13dffe..195bdc2ad0d 100644 --- a/tests/baselines/reference/multipleDeclarations.types +++ b/tests/baselines/reference/multipleDeclarations.types @@ -21,7 +21,7 @@ C.prototype.m = function() { this.nothing(); >this.nothing() : any >this.nothing : any ->this : { m: any; } +>this : { m: () => void; } >nothing : any } class X { diff --git a/tests/cases/compiler/jsFileClassPropertyType3.ts b/tests/cases/compiler/jsFileClassPropertyType3.ts new file mode 100644 index 00000000000..7c240e942fb --- /dev/null +++ b/tests/cases/compiler/jsFileClassPropertyType3.ts @@ -0,0 +1,18 @@ +// @allowJs: true +// @noEmit: true + +// @filename: foo.js +class C { + constructor() { + if (cond) { + this.p = null; + } + else { + this.p = 0; + } + } +} + +// @filename: bar.ts + +(new C()).p = "string"; // Error