JSMonk / hegel

An advanced static type checker
https://hegel.js.org
MIT License
2.1k stars 59 forks source link

Unsound subclassing is allowed #231

Open vkurchatkin opened 4 years ago

vkurchatkin commented 4 years ago
class A {
  foo() {
    return 1;
  }
}

class B extends A {
  foo() {
    return ''; // this shouldn't be allowed
  }
}

const b: A = new B;
const val = b.foo().toFixed(); // runtime error
JSMonk commented 4 years ago

It's a really interesting case. After I will fix it I will write an article about it. From one side, we can prevent extending a class with a new return/arguments types (Liskov Pattern). But, it's one of the most terrible things in TypeScript. Example From the other side is Flow approach Example. But, for implementation of the approach Hegel need to store all subclasses of the current class, and if your class is generic Thank you a lot for the interesting issue ^_^

thecotne commented 4 years ago

@JSMonk so do you want usage based typing after all?


in flow if you specify type in any class then all other implementations are checked for compatibility

class A {
  foo(): number {
    return 1;
  }
}

class B extends A {
  foo() {
    return '';// err
  }
}

const b = new A;
const val = b.foo();

flow's approach sounds like better idea specially if there is flag in config to disallow widening type when extending class (for people coming from typescript who like to have Liskov Pattern enforced in codebase)