TypeScript Version:
1.9.0-dev.20160405
Code
class Animal {
name: string;
}
class Dog extends Animal {
bark() {};
}
class Cat extends Animal {
meow() {};
}
class Box<V> {
item: V;
}
function f<T extends Box<Animal>>(box: T) {
box.item = new Cat(); // <-- This is perfectly valid and allowed by the constraint
return box; // <-- The returned type is T
}
let result = f(new Box<Dog>()); // Type of 'result' is inferred as Box<Dog>
result.item.bark(); // <-- No compilation error. Run-time error..
Expected behavior:
Type of result should be inferred as Box<Animal>.
result.item.bark(); should give a compilation error.
Actual behavior:
Type of result is inferred as Box<Dog>.
result.item.bark(); does not error at compile-time but does error at run-time.
Comments:
Type of box should be widened from T to Box<Animal> within the body of the function, as there is no (current) way to ensure the members of box are not reassigned with types incompatible to the ones specified in T. The return type should therefore be Box<Animal> and not T.
[Edits: rewritten main example, heavily shortened and removed unneeded sections]