-
Notifications
You must be signed in to change notification settings - Fork 13k
Closed
Closed
Copy link
Labels
BugA bug in TypeScriptA bug in TypeScriptFixedA PR has been merged for this issueA PR has been merged for this issue
Milestone
Description
TypeScript Version:
2.3.4 and 2.4.1
Code
interface IBaseModel {
id: string
}
class BaseClass {
model: IBaseModel
constructor() {
}
setModel(model: IBaseModel) {
this.model = model
}
getValueByName(name: string) {
return this.model[name];
}
}
interface IDerived1Model extends IBaseModel {
height: number;
}
class Derived1 extends BaseClass {
// Unsound override!
setModel(model: IDerived1Model) {
super.setModel(model);
// Do something with model...
}
}
interface IDerived2Model extends IBaseModel {
width: number;
}
class Derived2 extends BaseClass {
// Unsound override!
setModel(model: IDerived2Model) {
super.setModel(model);
// Do something with model...
}
}
const model1 = { id: "0", height: 42 };
const model2 = { id: "1", width: 24 };
const obj1 = new Derived1();
obj1.setModel(model1);
const obj2 = new Derived2();
obj2.setModel(model2);
const objs: BaseClass[] = [
obj1,
obj2
];
let variable: any = null;
for (const obj of objs) {
if (obj instanceof Derived1) {
variable = obj.getValueByName("height"); // Ok, obj is now of type `Derived1`
} else if (obj instanceof Derived2) {
variable = obj.getValueByName("width"); // Does not compile: Property 'getValueByName' does not exist on type 'never'
}
console.log("Value is: " + variable);
}
Expected behavior:
obj
is narrowed to Derived2
.
Actual behavior:
obj
is narrowed to never
.
More
See discussion here: https://stackoverflow.com/questions/45381122/typescript-type-narrowed-to-never-with-instanceof-in-an-if-else-statement
When the setModel
overrides use IBaseModel
as type, it works. However, even though the current code is unsound, I would expect it to compile.
Metadata
Metadata
Assignees
Labels
BugA bug in TypeScriptA bug in TypeScriptFixedA PR has been merged for this issueA PR has been merged for this issue