export {} // @strict: true declare let f1: (x: Object) => Object; declare let f2: (x: Object) => string; declare let f3: (x: string) => Object; declare let f4: (x: string) => string; f1 = f2; // Ok f1 = f3; // Error f1 = f4; // Error f2 = f1; // Error f2 = f3; // Error f2 = f4; // Error f3 = f1; // Ok f3 = f2; // Ok f3 = f4; // Ok f4 = f1; // Error f4 = f2; // Ok f4 = f3; // Error type Func = (x: T) => U; declare let g1: Func; declare let g2: Func; declare let g3: Func; declare let g4: Func; g1 = g2; // Ok g1 = g3; // Error g1 = g4; // Error g2 = g1; // Error g2 = g3; // Error g2 = g4; // Error g3 = g1; // Ok g3 = g2; // Ok g3 = g4; // Ok g4 = g1; // Error g4 = g2; // Ok g4 = g3; // Error declare let h1: Func, Object>; declare let h2: Func, string>; declare let h3: Func, Object>; declare let h4: Func, string>; h1 = h2; // Ok h1 = h3; // Ok h1 = h4; // Ok h2 = h1; // Error h2 = h3; // Error h2 = h4; // Ok h3 = h1; // Error h3 = h2; // Error h3 = h4; // Ok h4 = h1; // Error h4 = h2; // Error h4 = h3; // Error declare let i1: Func>; declare let i2: Func>; declare let i3: Func>; declare let i4: Func>; i1 = i2; // Error i1 = i3; // Error i1 = i4; // Error i2 = i1; // Ok i2 = i3; // Error i2 = i4; // Error i3 = i1; // Ok i3 = i2; // Error i3 = i4; // Error i4 = i1; // Ok i4 = i2; // Ok i4 = i3; // Ok interface Animal { animal: void } interface Dog extends Animal { dog: void } interface Cat extends Animal { cat: void } interface Comparer1 { compare(a: T, b: T): number; } declare let animalComparer1: Comparer1; declare let dogComparer1: Comparer1; animalComparer1 = dogComparer1; // Ok dogComparer1 = animalComparer1; // Ok interface Comparer2 { compare: (a: T, b: T) => number; } declare let animalComparer2: Comparer2; declare let dogComparer2: Comparer2; animalComparer2 = dogComparer2; // Error dogComparer2 = animalComparer2; // Ok // Crate is invariant in --strictFunctionTypes mode interface Crate { item: T; onSetItem: (item: T) => void; } declare let animalCrate: Crate; declare let dogCrate: Crate; // Errors below should elaborate the reason for invariance 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 = { foo(x: Input): Output }["foo"]; declare let f1: (cb: BivariantHack) => void; declare let f2: (cb: BivariantHack) => void; f1 = f2; f2 = f1; // Error }