Merge pull request #18976 from Microsoft/strictCallbackParameters

Strictly check callback parameters
This commit is contained in:
Anders Hejlsberg
2017-10-06 21:36:52 +01:00
committed by GitHub
6 changed files with 369 additions and 10 deletions

View File

@@ -87,9 +87,24 @@ tests/cases/compiler/strictFunctionTypesErrors.ts(126,1): error TS2322: Type 'Cr
tests/cases/compiler/strictFunctionTypesErrors.ts(127,1): error TS2322: Type 'Crate<Animal>' is not assignable to type 'Crate<Dog>'.
Types of property 'item' are incompatible.
Type 'Animal' is not assignable to type 'Dog'.
tests/cases/compiler/strictFunctionTypesErrors.ts(133,1): error TS2322: Type '(f: (x: Dog) => Dog) => void' is not assignable to type '(f: (x: Animal) => Animal) => void'.
Types of parameters 'f' and 'f' are incompatible.
Type 'Animal' is not assignable to type 'Dog'.
tests/cases/compiler/strictFunctionTypesErrors.ts(134,1): error TS2322: Type '(f: (x: Animal) => Animal) => void' is not assignable to type '(f: (x: Dog) => Dog) => void'.
Types of parameters 'f' and 'f' are incompatible.
Types of parameters 'x' and 'x' are incompatible.
Type 'Animal' is not assignable to type 'Dog'.
tests/cases/compiler/strictFunctionTypesErrors.ts(147,5): error TS2322: Type '(cb: (x: Animal) => Animal) => void' is not assignable to type '(cb: (x: Dog) => Animal) => void'.
Types of parameters 'cb' and 'cb' are incompatible.
Types of parameters 'x' and 'x' are incompatible.
Type 'Animal' is not assignable to type 'Dog'.
tests/cases/compiler/strictFunctionTypesErrors.ts(155,5): error TS2322: Type '(cb: (x: Animal) => Animal) => void' is not assignable to type '(cb: (x: Dog) => Animal) => void'.
Types of parameters 'cb' and 'cb' are incompatible.
Types of parameters 'x' and 'x' are incompatible.
Type 'Animal' is not assignable to type 'Dog'.
==== tests/cases/compiler/strictFunctionTypesErrors.ts (31 errors) ====
==== tests/cases/compiler/strictFunctionTypesErrors.ts (35 errors) ====
export {}
@@ -337,4 +352,51 @@ tests/cases/compiler/strictFunctionTypesErrors.ts(127,1): error TS2322: Type 'Cr
!!! error TS2322: Type 'Crate<Animal>' is not assignable to type 'Crate<Dog>'.
!!! error TS2322: Types of property 'item' are incompatible.
!!! error TS2322: Type 'Animal' is not assignable to type 'Dog'.
// Verify that callback parameters are strictly checked
declare let fc1: (f: (x: Animal) => Animal) => void;
declare let fc2: (f: (x: Dog) => Dog) => void;
fc1 = fc2; // Error
~~~
!!! error TS2322: Type '(f: (x: Dog) => Dog) => void' is not assignable to type '(f: (x: Animal) => Animal) => void'.
!!! error TS2322: Types of parameters 'f' and 'f' are incompatible.
!!! error TS2322: Type 'Animal' is not assignable to type 'Dog'.
fc2 = fc1; // Error
~~~
!!! error TS2322: Type '(f: (x: Animal) => Animal) => void' is not assignable to type '(f: (x: Dog) => Dog) => void'.
!!! error TS2322: Types of parameters 'f' and 'f' are incompatible.
!!! error TS2322: Types of parameters 'x' and 'x' are incompatible.
!!! error TS2322: Type 'Animal' is not assignable to type 'Dog'.
// Verify that callback parameters aren't loosely checked when types
// originate in method declarations
namespace n1 {
class Foo {
static f1(x: Animal): Animal { throw "wat"; }
static f2(x: Dog): Animal { throw "wat"; };
}
declare let f1: (cb: typeof Foo.f1) => void;
declare let f2: (cb: typeof Foo.f2) => void;
f1 = f2;
f2 = f1; // Error
~~
!!! error TS2322: Type '(cb: (x: Animal) => Animal) => void' is not assignable to type '(cb: (x: Dog) => Animal) => void'.
!!! error TS2322: Types of parameters 'cb' and 'cb' are incompatible.
!!! error TS2322: Types of parameters 'x' and 'x' are incompatible.
!!! error TS2322: Type 'Animal' is not assignable to type 'Dog'.
}
namespace n2 {
type BivariantHack<Input, Output> = { foo(x: Input): Output }["foo"];
declare let f1: (cb: BivariantHack<Animal, Animal>) => void;
declare let f2: (cb: BivariantHack<Dog, Animal>) => void;
f1 = f2;
f2 = f1; // Error
~~
!!! error TS2322: Type '(cb: (x: Animal) => Animal) => void' is not assignable to type '(cb: (x: Dog) => Animal) => void'.
!!! error TS2322: Types of parameters 'cb' and 'cb' are incompatible.
!!! error TS2322: Types of parameters 'x' and 'x' are incompatible.
!!! error TS2322: Type 'Animal' is not assignable to type 'Dog'.
}

View File

@@ -126,7 +126,35 @@ declare let dogCrate: Crate<Dog>;
animalCrate = dogCrate; // Error
dogCrate = animalCrate; // Error
// Verify that callback parameters are strictly checked
declare let fc1: (f: (x: Animal) => Animal) => void;
declare let fc2: (f: (x: Dog) => Dog) => void;
fc1 = fc2; // Error
fc2 = fc1; // Error
// Verify that callback parameters aren't loosely checked when types
// originate in method declarations
namespace n1 {
class Foo {
static f1(x: Animal): Animal { throw "wat"; }
static f2(x: Dog): Animal { throw "wat"; };
}
declare let f1: (cb: typeof Foo.f1) => void;
declare let f2: (cb: typeof Foo.f2) => void;
f1 = f2;
f2 = f1; // Error
}
namespace n2 {
type BivariantHack<Input, Output> = { foo(x: Input): Output }["foo"];
declare let f1: (cb: BivariantHack<Animal, Animal>) => void;
declare let f2: (cb: BivariantHack<Dog, Animal>) => void;
f1 = f2;
f2 = f1; // Error
}
//// [strictFunctionTypesErrors.js]
"use strict";
@@ -186,3 +214,25 @@ dogComparer2 = animalComparer2; // Ok
// Errors below should elaborate the reason for invariance
animalCrate = dogCrate; // Error
dogCrate = animalCrate; // Error
fc1 = fc2; // Error
fc2 = fc1; // Error
// Verify that callback parameters aren't loosely checked when types
// originate in method declarations
var n1;
(function (n1) {
var Foo = /** @class */ (function () {
function Foo() {
}
Foo.f1 = function (x) { throw "wat"; };
Foo.f2 = function (x) { throw "wat"; };
;
return Foo;
}());
f1 = f2;
f2 = f1; // Error
})(n1 || (n1 = {}));
var n2;
(function (n2) {
f1 = f2;
f2 = f1; // Error
})(n2 || (n2 = {}));

View File

@@ -400,3 +400,105 @@ dogCrate = animalCrate; // Error
>dogCrate : Symbol(dogCrate, Decl(strictFunctionTypesErrors.ts, 121, 11))
>animalCrate : Symbol(animalCrate, Decl(strictFunctionTypesErrors.ts, 120, 11))
// Verify that callback parameters are strictly checked
declare let fc1: (f: (x: Animal) => Animal) => void;
>fc1 : Symbol(fc1, Decl(strictFunctionTypesErrors.ts, 130, 11))
>f : Symbol(f, Decl(strictFunctionTypesErrors.ts, 130, 18))
>x : Symbol(x, Decl(strictFunctionTypesErrors.ts, 130, 22))
>Animal : Symbol(Animal, Decl(strictFunctionTypesErrors.ts, 87, 8))
>Animal : Symbol(Animal, Decl(strictFunctionTypesErrors.ts, 87, 8))
declare let fc2: (f: (x: Dog) => Dog) => void;
>fc2 : Symbol(fc2, Decl(strictFunctionTypesErrors.ts, 131, 11))
>f : Symbol(f, Decl(strictFunctionTypesErrors.ts, 131, 18))
>x : Symbol(x, Decl(strictFunctionTypesErrors.ts, 131, 22))
>Dog : Symbol(Dog, Decl(strictFunctionTypesErrors.ts, 89, 33))
>Dog : Symbol(Dog, Decl(strictFunctionTypesErrors.ts, 89, 33))
fc1 = fc2; // Error
>fc1 : Symbol(fc1, Decl(strictFunctionTypesErrors.ts, 130, 11))
>fc2 : Symbol(fc2, Decl(strictFunctionTypesErrors.ts, 131, 11))
fc2 = fc1; // Error
>fc2 : Symbol(fc2, Decl(strictFunctionTypesErrors.ts, 131, 11))
>fc1 : Symbol(fc1, Decl(strictFunctionTypesErrors.ts, 130, 11))
// Verify that callback parameters aren't loosely checked when types
// originate in method declarations
namespace n1 {
>n1 : Symbol(n1, Decl(strictFunctionTypesErrors.ts, 133, 10))
class Foo {
>Foo : Symbol(Foo, Decl(strictFunctionTypesErrors.ts, 138, 14))
static f1(x: Animal): Animal { throw "wat"; }
>f1 : Symbol(Foo.f1, Decl(strictFunctionTypesErrors.ts, 139, 15))
>x : Symbol(x, Decl(strictFunctionTypesErrors.ts, 140, 18))
>Animal : Symbol(Animal, Decl(strictFunctionTypesErrors.ts, 87, 8))
>Animal : Symbol(Animal, Decl(strictFunctionTypesErrors.ts, 87, 8))
static f2(x: Dog): Animal { throw "wat"; };
>f2 : Symbol(Foo.f2, Decl(strictFunctionTypesErrors.ts, 140, 53))
>x : Symbol(x, Decl(strictFunctionTypesErrors.ts, 141, 18))
>Dog : Symbol(Dog, Decl(strictFunctionTypesErrors.ts, 89, 33))
>Animal : Symbol(Animal, Decl(strictFunctionTypesErrors.ts, 87, 8))
}
declare let f1: (cb: typeof Foo.f1) => void;
>f1 : Symbol(f1, Decl(strictFunctionTypesErrors.ts, 143, 15))
>cb : Symbol(cb, Decl(strictFunctionTypesErrors.ts, 143, 21))
>Foo.f1 : Symbol(Foo.f1, Decl(strictFunctionTypesErrors.ts, 139, 15))
>Foo : Symbol(Foo, Decl(strictFunctionTypesErrors.ts, 138, 14))
>f1 : Symbol(Foo.f1, Decl(strictFunctionTypesErrors.ts, 139, 15))
declare let f2: (cb: typeof Foo.f2) => void;
>f2 : Symbol(f2, Decl(strictFunctionTypesErrors.ts, 144, 15))
>cb : Symbol(cb, Decl(strictFunctionTypesErrors.ts, 144, 21))
>Foo.f2 : Symbol(Foo.f2, Decl(strictFunctionTypesErrors.ts, 140, 53))
>Foo : Symbol(Foo, Decl(strictFunctionTypesErrors.ts, 138, 14))
>f2 : Symbol(Foo.f2, Decl(strictFunctionTypesErrors.ts, 140, 53))
f1 = f2;
>f1 : Symbol(f1, Decl(strictFunctionTypesErrors.ts, 143, 15))
>f2 : Symbol(f2, Decl(strictFunctionTypesErrors.ts, 144, 15))
f2 = f1; // Error
>f2 : Symbol(f2, Decl(strictFunctionTypesErrors.ts, 144, 15))
>f1 : Symbol(f1, Decl(strictFunctionTypesErrors.ts, 143, 15))
}
namespace n2 {
>n2 : Symbol(n2, Decl(strictFunctionTypesErrors.ts, 147, 1))
type BivariantHack<Input, Output> = { foo(x: Input): Output }["foo"];
>BivariantHack : Symbol(BivariantHack, Decl(strictFunctionTypesErrors.ts, 149, 14))
>Input : Symbol(Input, Decl(strictFunctionTypesErrors.ts, 150, 23))
>Output : Symbol(Output, Decl(strictFunctionTypesErrors.ts, 150, 29))
>foo : Symbol(foo, Decl(strictFunctionTypesErrors.ts, 150, 41))
>x : Symbol(x, Decl(strictFunctionTypesErrors.ts, 150, 46))
>Input : Symbol(Input, Decl(strictFunctionTypesErrors.ts, 150, 23))
>Output : Symbol(Output, Decl(strictFunctionTypesErrors.ts, 150, 29))
declare let f1: (cb: BivariantHack<Animal, Animal>) => void;
>f1 : Symbol(f1, Decl(strictFunctionTypesErrors.ts, 151, 15))
>cb : Symbol(cb, Decl(strictFunctionTypesErrors.ts, 151, 21))
>BivariantHack : Symbol(BivariantHack, Decl(strictFunctionTypesErrors.ts, 149, 14))
>Animal : Symbol(Animal, Decl(strictFunctionTypesErrors.ts, 87, 8))
>Animal : Symbol(Animal, Decl(strictFunctionTypesErrors.ts, 87, 8))
declare let f2: (cb: BivariantHack<Dog, Animal>) => void;
>f2 : Symbol(f2, Decl(strictFunctionTypesErrors.ts, 152, 15))
>cb : Symbol(cb, Decl(strictFunctionTypesErrors.ts, 152, 21))
>BivariantHack : Symbol(BivariantHack, Decl(strictFunctionTypesErrors.ts, 149, 14))
>Dog : Symbol(Dog, Decl(strictFunctionTypesErrors.ts, 89, 33))
>Animal : Symbol(Animal, Decl(strictFunctionTypesErrors.ts, 87, 8))
f1 = f2;
>f1 : Symbol(f1, Decl(strictFunctionTypesErrors.ts, 151, 15))
>f2 : Symbol(f2, Decl(strictFunctionTypesErrors.ts, 152, 15))
f2 = f1; // Error
>f2 : Symbol(f2, Decl(strictFunctionTypesErrors.ts, 152, 15))
>f1 : Symbol(f1, Decl(strictFunctionTypesErrors.ts, 151, 15))
}

View File

@@ -454,3 +454,113 @@ dogCrate = animalCrate; // Error
>dogCrate : Crate<Dog>
>animalCrate : Crate<Animal>
// Verify that callback parameters are strictly checked
declare let fc1: (f: (x: Animal) => Animal) => void;
>fc1 : (f: (x: Animal) => Animal) => void
>f : (x: Animal) => Animal
>x : Animal
>Animal : Animal
>Animal : Animal
declare let fc2: (f: (x: Dog) => Dog) => void;
>fc2 : (f: (x: Dog) => Dog) => void
>f : (x: Dog) => Dog
>x : Dog
>Dog : Dog
>Dog : Dog
fc1 = fc2; // Error
>fc1 = fc2 : (f: (x: Dog) => Dog) => void
>fc1 : (f: (x: Animal) => Animal) => void
>fc2 : (f: (x: Dog) => Dog) => void
fc2 = fc1; // Error
>fc2 = fc1 : (f: (x: Animal) => Animal) => void
>fc2 : (f: (x: Dog) => Dog) => void
>fc1 : (f: (x: Animal) => Animal) => void
// Verify that callback parameters aren't loosely checked when types
// originate in method declarations
namespace n1 {
>n1 : typeof n1
class Foo {
>Foo : Foo
static f1(x: Animal): Animal { throw "wat"; }
>f1 : (x: Animal) => Animal
>x : Animal
>Animal : Animal
>Animal : Animal
>"wat" : "wat"
static f2(x: Dog): Animal { throw "wat"; };
>f2 : (x: Dog) => Animal
>x : Dog
>Dog : Dog
>Animal : Animal
>"wat" : "wat"
}
declare let f1: (cb: typeof Foo.f1) => void;
>f1 : (cb: (x: Animal) => Animal) => void
>cb : (x: Animal) => Animal
>Foo.f1 : (x: Animal) => Animal
>Foo : typeof Foo
>f1 : (x: Animal) => Animal
declare let f2: (cb: typeof Foo.f2) => void;
>f2 : (cb: (x: Dog) => Animal) => void
>cb : (x: Dog) => Animal
>Foo.f2 : (x: Dog) => Animal
>Foo : typeof Foo
>f2 : (x: Dog) => Animal
f1 = f2;
>f1 = f2 : (cb: (x: Dog) => Animal) => void
>f1 : (cb: (x: Animal) => Animal) => void
>f2 : (cb: (x: Dog) => Animal) => void
f2 = f1; // Error
>f2 = f1 : (cb: (x: Animal) => Animal) => void
>f2 : (cb: (x: Dog) => Animal) => void
>f1 : (cb: (x: Animal) => Animal) => void
}
namespace n2 {
>n2 : typeof n2
type BivariantHack<Input, Output> = { foo(x: Input): Output }["foo"];
>BivariantHack : (x: Input) => Output
>Input : Input
>Output : Output
>foo : (x: Input) => Output
>x : Input
>Input : Input
>Output : Output
declare let f1: (cb: BivariantHack<Animal, Animal>) => void;
>f1 : (cb: (x: Animal) => Animal) => void
>cb : (x: Animal) => Animal
>BivariantHack : (x: Input) => Output
>Animal : Animal
>Animal : Animal
declare let f2: (cb: BivariantHack<Dog, Animal>) => void;
>f2 : (cb: (x: Dog) => Animal) => void
>cb : (x: Dog) => Animal
>BivariantHack : (x: Input) => Output
>Dog : Dog
>Animal : Animal
f1 = f2;
>f1 = f2 : (cb: (x: Dog) => Animal) => void
>f1 : (cb: (x: Animal) => Animal) => void
>f2 : (cb: (x: Dog) => Animal) => void
f2 = f1; // Error
>f2 = f1 : (cb: (x: Animal) => Animal) => void
>f2 : (cb: (x: Dog) => Animal) => void
>f1 : (cb: (x: Animal) => Animal) => void
}

View File

@@ -126,3 +126,32 @@ declare let dogCrate: Crate<Dog>;
animalCrate = dogCrate; // Error
dogCrate = animalCrate; // Error
// Verify that callback parameters are strictly checked
declare let fc1: (f: (x: Animal) => Animal) => void;
declare let fc2: (f: (x: Dog) => Dog) => void;
fc1 = fc2; // Error
fc2 = fc1; // Error
// Verify that callback parameters aren't loosely checked when types
// originate in method declarations
namespace n1 {
class Foo {
static f1(x: Animal): Animal { throw "wat"; }
static f2(x: Dog): Animal { throw "wat"; };
}
declare let f1: (cb: typeof Foo.f1) => void;
declare let f2: (cb: typeof Foo.f2) => void;
f1 = f2;
f2 = f1; // Error
}
namespace n2 {
type BivariantHack<Input, Output> = { foo(x: Input): Output }["foo"];
declare let f1: (cb: BivariantHack<Animal, Animal>) => void;
declare let f2: (cb: BivariantHack<Dog, Animal>) => void;
f1 = f2;
f2 = f1; // Error
}