Merge pull request #17314 from gcnew/checkTypeGuardConstraintConformance
Check type guard constraint conformance
This commit is contained in:
commit
759ee288f2
|
@ -17996,6 +17996,8 @@ namespace ts {
|
|||
return;
|
||||
}
|
||||
|
||||
checkSourceElement(node.type);
|
||||
|
||||
const { parameterName } = node;
|
||||
if (isThisTypePredicate(typePredicate)) {
|
||||
getTypeFromThisTypeNode(parameterName as ThisTypeNode);
|
||||
|
|
|
@ -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<number>' 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;
|
||||
}
|
||||
}
|
||||
|
||||
// repro #17297
|
||||
|
||||
type Keys = 'a'|'b'|'c'
|
||||
type KeySet<T extends Keys> = { [k in T]: true }
|
||||
|
||||
// expected an error, since Keys doesn't have a 'd'
|
||||
declare function hasKey<T extends Keys>(x: KeySet<T>): x is KeySet<T|'d'>;
|
||||
~~~~~
|
||||
!!! 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<T extends Foo> {
|
||||
foo: T;
|
||||
isFoo(): this is NeedsFoo<Bar>; // 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<Bar>; // error, as expected
|
||||
~~~
|
||||
!!! error TS2344: Type 'Bar' does not satisfy the constraint 'Foo'.
|
||||
declare var alsoAnError: NeedsFoo<number>; // also error, as expected
|
||||
~~~~~~
|
||||
!!! error TS2344: Type 'number' does not satisfy the constraint 'Foo'.
|
||||
declare function newError1(x: any): x is NeedsFoo<Bar>; // should error
|
||||
~~~
|
||||
!!! error TS2344: Type 'Bar' does not satisfy the constraint 'Foo'.
|
||||
declare function newError2(x: any): x is NeedsFoo<number>; // should error
|
||||
~~~~~~
|
||||
!!! error TS2344: Type 'number' does not satisfy the constraint 'Foo'.
|
||||
declare function newError3(x: number): x is NeedsFoo<number>; // should error
|
||||
~~~~~~~~~~~~~~~~
|
||||
!!! error TS2677: A type predicate's type must be assignable to its parameter's type.
|
||||
!!! error TS2677: Type 'NeedsFoo<number>' is not assignable to type 'number'.
|
||||
~~~~~~
|
||||
!!! error TS2344: Type 'number' does not satisfy the constraint 'Foo'.
|
||||
|
|
@ -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<T extends Keys> = { [k in T]: true }
|
||||
|
||||
// expected an error, since Keys doesn't have a 'd'
|
||||
declare function hasKey<T extends Keys>(x: KeySet<T>): x is KeySet<T|'d'>;
|
||||
|
||||
type Foo = { 'a': string; }
|
||||
type Bar = { 'a': number; }
|
||||
|
||||
interface NeedsFoo<T extends Foo> {
|
||||
foo: T;
|
||||
isFoo(): this is NeedsFoo<Bar>; // should error
|
||||
};
|
||||
|
||||
declare var anError: NeedsFoo<Bar>; // error, as expected
|
||||
declare var alsoAnError: NeedsFoo<number>; // also error, as expected
|
||||
declare function newError1(x: any): x is NeedsFoo<Bar>; // should error
|
||||
declare function newError2(x: any): x is NeedsFoo<number>; // should error
|
||||
declare function newError3(x: number): x is NeedsFoo<number>; // 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;
|
||||
}
|
||||
;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
// repro #17297
|
||||
|
||||
type Keys = 'a'|'b'|'c'
|
||||
type KeySet<T extends Keys> = { [k in T]: true }
|
||||
|
||||
// expected an error, since Keys doesn't have a 'd'
|
||||
declare function hasKey<T extends Keys>(x: KeySet<T>): x is KeySet<T|'d'>;
|
||||
|
||||
type Foo = { 'a': string; }
|
||||
type Bar = { 'a': number; }
|
||||
|
||||
interface NeedsFoo<T extends Foo> {
|
||||
foo: T;
|
||||
isFoo(): this is NeedsFoo<Bar>; // should error
|
||||
};
|
||||
|
||||
declare var anError: NeedsFoo<Bar>; // error, as expected
|
||||
declare var alsoAnError: NeedsFoo<number>; // also error, as expected
|
||||
declare function newError1(x: any): x is NeedsFoo<Bar>; // should error
|
||||
declare function newError2(x: any): x is NeedsFoo<number>; // should error
|
||||
declare function newError3(x: number): x is NeedsFoo<number>; // should error
|
||||
|
|
Loading…
Reference in a new issue