From 51b183a0a1f5006e9f0606eb2da7d945f719f8c4 Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Mon, 17 Jul 2017 15:44:58 -0700 Subject: [PATCH] Feedback from #17211 --- src/compiler/checker.ts | 14 +++--- .../reference/jsdocTypeTagCast.errors.txt | 43 ++++++++++++++----- tests/baselines/reference/jsdocTypeTagCast.js | 21 +++++++++ .../conformance/jsdoc/jsdocTypeTagCast.ts | 12 ++++++ 4 files changed, 71 insertions(+), 19 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 141928efb5073..be14b7d95c924 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -17740,14 +17740,12 @@ namespace ts { } function checkParenthesizedExpression(node: ParenthesizedExpression, checkMode?: CheckMode): Type { - if (isInJavaScriptFile(node)) { - if (node.jsDoc) { - const typecasts = flatten(map(node.jsDoc, doc => filter(doc.tags, tag => tag.kind === SyntaxKind.JSDocTypeTag))); - if (typecasts && typecasts.length) { - // We should have already issued an error if there were multiple type jsdocs - const cast = typecasts[0] as JSDocTypeTag; - return checkAssertionWorker(cast, cast.typeExpression.type, node.expression, checkMode); - } + if (isInJavaScriptFile(node) && node.jsDoc) { + const typecasts = flatMap(node.jsDoc, doc => filter(doc.tags, tag => tag.kind === SyntaxKind.JSDocTypeTag)); + if (typecasts && typecasts.length) { + // We should have already issued an error if there were multiple type jsdocs + const cast = typecasts[0] as JSDocTypeTag; + return checkAssertionWorker(cast, cast.typeExpression.type, node.expression, checkMode); } } return checkExpression(node.expression, checkMode); diff --git a/tests/baselines/reference/jsdocTypeTagCast.errors.txt b/tests/baselines/reference/jsdocTypeTagCast.errors.txt index 07a7bc94bc7f0..f1f53ec1ecbe6 100644 --- a/tests/baselines/reference/jsdocTypeTagCast.errors.txt +++ b/tests/baselines/reference/jsdocTypeTagCast.errors.txt @@ -1,25 +1,29 @@ tests/cases/conformance/jsdoc/b.js(4,13): error TS2352: Type 'number' cannot be converted to type 'string'. -tests/cases/conformance/jsdoc/b.js(39,16): error TS2352: Type 'SomeOther' cannot be converted to type 'SomeBase'. +tests/cases/conformance/jsdoc/b.js(45,16): error TS2352: Type 'SomeOther' cannot be converted to type 'SomeBase'. Property 'p' is missing in type 'SomeOther'. -tests/cases/conformance/jsdoc/b.js(43,19): error TS2352: Type 'SomeOther' cannot be converted to type 'SomeDerived'. +tests/cases/conformance/jsdoc/b.js(49,19): error TS2352: Type 'SomeOther' cannot be converted to type 'SomeDerived'. Property 'x' is missing in type 'SomeOther'. -tests/cases/conformance/jsdoc/b.js(45,17): error TS2352: Type 'SomeDerived' cannot be converted to type 'SomeOther'. +tests/cases/conformance/jsdoc/b.js(51,17): error TS2352: Type 'SomeDerived' cannot be converted to type 'SomeOther'. Property 'q' is missing in type 'SomeDerived'. -tests/cases/conformance/jsdoc/b.js(46,17): error TS2352: Type 'SomeBase' cannot be converted to type 'SomeOther'. +tests/cases/conformance/jsdoc/b.js(52,17): error TS2352: Type 'SomeBase' cannot be converted to type 'SomeOther'. Property 'q' is missing in type 'SomeBase'. -tests/cases/conformance/jsdoc/b.js(54,8): error TS2352: Type 'boolean' cannot be converted to type 'string | number'. -tests/cases/conformance/jsdoc/b.js(54,15): error TS2304: Cannot find name 'numOrStr'. -tests/cases/conformance/jsdoc/b.js(54,24): error TS1005: '}' expected. -tests/cases/conformance/jsdoc/b.js(54,38): error TS2454: Variable 'numOrStr' is used before being assigned. -tests/cases/conformance/jsdoc/b.js(55,2): error TS2322: Type 'string | number' is not assignable to type 'string'. +tests/cases/conformance/jsdoc/b.js(58,1): error TS2322: Type '{ p: string | number | undefined; }' is not assignable to type 'SomeBase'. + Types of property 'p' are incompatible. + Type 'string | number | undefined' is not assignable to type 'number'. + Type 'undefined' is not assignable to type 'number'. +tests/cases/conformance/jsdoc/b.js(66,8): error TS2352: Type 'boolean' cannot be converted to type 'string | number'. +tests/cases/conformance/jsdoc/b.js(66,15): error TS2304: Cannot find name 'numOrStr'. +tests/cases/conformance/jsdoc/b.js(66,24): error TS1005: '}' expected. +tests/cases/conformance/jsdoc/b.js(66,38): error TS2454: Variable 'numOrStr' is used before being assigned. +tests/cases/conformance/jsdoc/b.js(67,2): error TS2322: Type 'string | number' is not assignable to type 'string'. Type 'number' is not assignable to type 'string'. -tests/cases/conformance/jsdoc/b.js(55,8): error TS2454: Variable 'numOrStr' is used before being assigned. +tests/cases/conformance/jsdoc/b.js(67,8): error TS2454: Variable 'numOrStr' is used before being assigned. ==== tests/cases/conformance/jsdoc/a.ts (0 errors) ==== var W: string; -==== tests/cases/conformance/jsdoc/b.js (11 errors) ==== +==== tests/cases/conformance/jsdoc/b.js (12 errors) ==== // @ts-check var W = /** @type {string} */(/** @type {*} */ (4)); @@ -53,10 +57,16 @@ tests/cases/conformance/jsdoc/b.js(55,8): error TS2454: Variable 'numOrStr' is u } } + function SomeFakeClass() { + /** @type {string|number} */ + this.p = "bar"; + } + // Type assertion should check for assignability in either direction var someBase = new SomeBase(); var someDerived = new SomeDerived(); var someOther = new SomeOther(); + var someFakeClass = new SomeFakeClass(); someBase = /** @type {SomeBase} */(someDerived); someBase = /** @type {SomeBase} */(someBase); @@ -82,6 +92,17 @@ tests/cases/conformance/jsdoc/b.js(55,8): error TS2454: Variable 'numOrStr' is u !!! error TS2352: Property 'q' is missing in type 'SomeBase'. someOther = /** @type {SomeOther} */(someOther); + someFakeClass = someBase; + someFakeClass = someDerived; + + someBase = someFakeClass; // Error + ~~~~~~~~ +!!! error TS2322: Type '{ p: string | number | undefined; }' is not assignable to type 'SomeBase'. +!!! error TS2322: Types of property 'p' are incompatible. +!!! error TS2322: Type 'string | number | undefined' is not assignable to type 'number'. +!!! error TS2322: Type 'undefined' is not assignable to type 'number'. + someBase = /** @type {SomeBase} */(someFakeClass); + // Type assertion cannot be a type-predicate type /** @type {number | string} */ var numOrStr; diff --git a/tests/baselines/reference/jsdocTypeTagCast.js b/tests/baselines/reference/jsdocTypeTagCast.js index 979ccfd704919..c2df50cd6dd4a 100644 --- a/tests/baselines/reference/jsdocTypeTagCast.js +++ b/tests/baselines/reference/jsdocTypeTagCast.js @@ -35,10 +35,16 @@ class SomeOther { } } +function SomeFakeClass() { + /** @type {string|number} */ + this.p = "bar"; +} + // Type assertion should check for assignability in either direction var someBase = new SomeBase(); var someDerived = new SomeDerived(); var someOther = new SomeOther(); +var someFakeClass = new SomeFakeClass(); someBase = /** @type {SomeBase} */(someDerived); someBase = /** @type {SomeBase} */(someBase); @@ -52,6 +58,12 @@ someOther = /** @type {SomeOther} */(someDerived); // Error someOther = /** @type {SomeOther} */(someBase); // Error someOther = /** @type {SomeOther} */(someOther); +someFakeClass = someBase; +someFakeClass = someDerived; + +someBase = someFakeClass; // Error +someBase = /** @type {SomeBase} */(someFakeClass); + // Type assertion cannot be a type-predicate type /** @type {number | string} */ var numOrStr; @@ -107,10 +119,15 @@ var SomeOther = (function () { } return SomeOther; }()); +function SomeFakeClass() { + /** @type {string|number} */ + this.p = "bar"; +} // Type assertion should check for assignability in either direction var someBase = new SomeBase(); var someDerived = new SomeDerived(); var someOther = new SomeOther(); +var someFakeClass = new SomeFakeClass(); someBase = (someDerived); someBase = (someBase); someBase = (someOther); // Error @@ -120,6 +137,10 @@ someDerived = (someOther); // Error someOther = (someDerived); // Error someOther = (someBase); // Error someOther = (someOther); +someFakeClass = someBase; +someFakeClass = someDerived; +someBase = someFakeClass; // Error +someBase = (someFakeClass); // Type assertion cannot be a type-predicate type /** @type {number | string} */ var numOrStr; diff --git a/tests/cases/conformance/jsdoc/jsdocTypeTagCast.ts b/tests/cases/conformance/jsdoc/jsdocTypeTagCast.ts index 62bc549cf2c84..60ca43b053346 100644 --- a/tests/cases/conformance/jsdoc/jsdocTypeTagCast.ts +++ b/tests/cases/conformance/jsdoc/jsdocTypeTagCast.ts @@ -37,10 +37,16 @@ class SomeOther { } } +function SomeFakeClass() { + /** @type {string|number} */ + this.p = "bar"; +} + // Type assertion should check for assignability in either direction var someBase = new SomeBase(); var someDerived = new SomeDerived(); var someOther = new SomeOther(); +var someFakeClass = new SomeFakeClass(); someBase = /** @type {SomeBase} */(someDerived); someBase = /** @type {SomeBase} */(someBase); @@ -54,6 +60,12 @@ someOther = /** @type {SomeOther} */(someDerived); // Error someOther = /** @type {SomeOther} */(someBase); // Error someOther = /** @type {SomeOther} */(someOther); +someFakeClass = someBase; +someFakeClass = someDerived; + +someBase = someFakeClass; // Error +someBase = /** @type {SomeBase} */(someFakeClass); + // Type assertion cannot be a type-predicate type /** @type {number | string} */ var numOrStr;