diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index a312f91c8f6..043e9755ce2 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -17996,6 +17996,8 @@ namespace ts { return; } + checkSourceElement(node.type); + const { parameterName } = node; if (isThisTypePredicate(typePredicate)) { getTypeFromThisTypeNode(parameterName as ThisTypeNode); diff --git a/tests/baselines/reference/typeGuardFunctionErrors.errors.txt b/tests/baselines/reference/typeGuardFunctionErrors.errors.txt index 63442a93b6b..46455687af2 100644 --- a/tests/baselines/reference/typeGuardFunctionErrors.errors.txt +++ b/tests/baselines/reference/typeGuardFunctionErrors.errors.txt @@ -62,9 +62,21 @@ tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(123,20 tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(128,34): error TS1230: A type predicate cannot reference element 'p1' in a binding pattern. tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(132,34): error TS1230: A type predicate cannot reference element 'p1' in a binding pattern. tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(136,39): error TS1230: A type predicate cannot reference element 'p1' in a binding pattern. +tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(152,68): error TS2344: Type 'T | "d"' does not satisfy the constraint 'Keys'. + Type '"d"' is not assignable to type 'Keys'. +tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(159,31): error TS2344: Type 'Bar' does not satisfy the constraint 'Foo'. + Types of property ''a'' are incompatible. + Type 'number' is not assignable to type 'string'. +tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(162,31): error TS2344: Type 'Bar' does not satisfy the constraint 'Foo'. +tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(163,35): error TS2344: Type 'number' does not satisfy the constraint 'Foo'. +tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(164,51): error TS2344: Type 'Bar' does not satisfy the constraint 'Foo'. +tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(165,51): error TS2344: Type 'number' does not satisfy the constraint 'Foo'. +tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(166,45): error TS2677: A type predicate's type must be assignable to its parameter's type. + Type 'NeedsFoo' is not assignable to type 'number'. +tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(166,54): error TS2344: Type 'number' does not satisfy the constraint 'Foo'. -==== tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts (54 errors) ==== +==== tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts (62 errors) ==== class A { ~ !!! error TS2300: Duplicate identifier 'A'. @@ -175,7 +187,7 @@ tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(136,39 // No type guard in if statement if (hasNoTypeGuard(a)) { - a.propB; + a.propB; ~~~~~ !!! error TS2551: Property 'propB' does not exist on type 'A'. Did you mean 'propA'? } @@ -208,7 +220,7 @@ tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(136,39 return true; }; - // No matching signature + // No matching signature var assign3: (p1, p2) => p1 is A; assign3 = function(p1, p2, p3): p1 is A { ~~~~~~~ @@ -326,4 +338,47 @@ tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(136,39 var x: A; if (hasMissingParameter()) { x.propA; - } \ No newline at end of file + } + + // repro #17297 + + type Keys = 'a'|'b'|'c' + type KeySet = { [k in T]: true } + + // expected an error, since Keys doesn't have a 'd' + declare function hasKey(x: KeySet): x is KeySet; + ~~~~~ +!!! error TS2344: Type 'T | "d"' does not satisfy the constraint 'Keys'. +!!! error TS2344: Type '"d"' is not assignable to type 'Keys'. + + type Foo = { 'a': string; } + type Bar = { 'a': number; } + + interface NeedsFoo { + foo: T; + isFoo(): this is NeedsFoo; // should error + ~~~ +!!! error TS2344: Type 'Bar' does not satisfy the constraint 'Foo'. +!!! error TS2344: Types of property ''a'' are incompatible. +!!! error TS2344: Type 'number' is not assignable to type 'string'. + }; + + declare var anError: NeedsFoo; // error, as expected + ~~~ +!!! error TS2344: Type 'Bar' does not satisfy the constraint 'Foo'. + declare var alsoAnError: NeedsFoo; // also error, as expected + ~~~~~~ +!!! error TS2344: Type 'number' does not satisfy the constraint 'Foo'. + declare function newError1(x: any): x is NeedsFoo; // should error + ~~~ +!!! error TS2344: Type 'Bar' does not satisfy the constraint 'Foo'. + declare function newError2(x: any): x is NeedsFoo; // should error + ~~~~~~ +!!! error TS2344: Type 'number' does not satisfy the constraint 'Foo'. + declare function newError3(x: number): x is NeedsFoo; // should error + ~~~~~~~~~~~~~~~~ +!!! error TS2677: A type predicate's type must be assignable to its parameter's type. +!!! error TS2677: Type 'NeedsFoo' is not assignable to type 'number'. + ~~~~~~ +!!! error TS2344: Type 'number' does not satisfy the constraint 'Foo'. + \ No newline at end of file diff --git a/tests/baselines/reference/typeGuardFunctionErrors.js b/tests/baselines/reference/typeGuardFunctionErrors.js index cc773ae11b1..12ffab852d8 100644 --- a/tests/baselines/reference/typeGuardFunctionErrors.js +++ b/tests/baselines/reference/typeGuardFunctionErrors.js @@ -67,7 +67,7 @@ if (funA(0, a)) { // No type guard in if statement if (hasNoTypeGuard(a)) { - a.propB; + a.propB; } // Type predicate type is not assignable @@ -86,7 +86,7 @@ assign2 = function(p1, p2): p2 is A { return true; }; -// No matching signature +// No matching signature var assign3: (p1, p2) => p1 is A; assign3 = function(p1, p2, p3): p1 is A { return true; @@ -142,7 +142,30 @@ function b7({a, b, c: {p1}}, p2, p3): p1 is A { var x: A; if (hasMissingParameter()) { x.propA; -} +} + +// repro #17297 + +type Keys = 'a'|'b'|'c' +type KeySet = { [k in T]: true } + +// expected an error, since Keys doesn't have a 'd' +declare function hasKey(x: KeySet): x is KeySet; + +type Foo = { 'a': string; } +type Bar = { 'a': number; } + +interface NeedsFoo { + foo: T; + isFoo(): this is NeedsFoo; // should error +}; + +declare var anError: NeedsFoo; // error, as expected +declare var alsoAnError: NeedsFoo; // also error, as expected +declare function newError1(x: any): x is NeedsFoo; // should error +declare function newError2(x: any): x is NeedsFoo; // should error +declare function newError3(x: number): x is NeedsFoo; // should error + //// [typeGuardFunctionErrors.js] var __extends = (this && this.__extends) || (function () { @@ -224,7 +247,7 @@ var assign2; assign2 = function (p1, p2) { return true; }; -// No matching signature +// No matching signature var assign3; assign3 = function (p1, p2, p3) { return true; @@ -290,3 +313,4 @@ var x; if (hasMissingParameter()) { x.propA; } +; diff --git a/tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts b/tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts index 688099280c5..eb61473c5cc 100644 --- a/tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts +++ b/tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts @@ -67,7 +67,7 @@ if (funA(0, a)) { // No type guard in if statement if (hasNoTypeGuard(a)) { - a.propB; + a.propB; } // Type predicate type is not assignable @@ -86,7 +86,7 @@ assign2 = function(p1, p2): p2 is A { return true; }; -// No matching signature +// No matching signature var assign3: (p1, p2) => p1 is A; assign3 = function(p1, p2, p3): p1 is A { return true; @@ -142,4 +142,26 @@ function b7({a, b, c: {p1}}, p2, p3): p1 is A { var x: A; if (hasMissingParameter()) { x.propA; -} \ No newline at end of file +} + +// repro #17297 + +type Keys = 'a'|'b'|'c' +type KeySet = { [k in T]: true } + +// expected an error, since Keys doesn't have a 'd' +declare function hasKey(x: KeySet): x is KeySet; + +type Foo = { 'a': string; } +type Bar = { 'a': number; } + +interface NeedsFoo { + foo: T; + isFoo(): this is NeedsFoo; // should error +}; + +declare var anError: NeedsFoo; // error, as expected +declare var alsoAnError: NeedsFoo; // also error, as expected +declare function newError1(x: any): x is NeedsFoo; // should error +declare function newError2(x: any): x is NeedsFoo; // should error +declare function newError3(x: number): x is NeedsFoo; // should error