Skip to content

strictFunctionTypes shouldn't prevent method overriding #19004

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
falsandtru opened this issue Oct 7, 2017 · 3 comments
Closed

strictFunctionTypes shouldn't prevent method overriding #19004

falsandtru opened this issue Oct 7, 2017 · 3 comments

Comments

@falsandtru
Copy link
Contributor

falsandtru commented Oct 7, 2017

As another point of #18963, strictFunctionTypes prevents some method overriding. TypeScript should relax strictFunctionTypes checks of method overriding. The current restriction is excessive on object-oriented programming.

cc @ahejlsberg

TypeScript Version: master

Code

declare class C {
  a(f: (a: C) => C): void;
  b(): (a: C) => C;
}
declare class D extends C {
  p: void;
  a(f: (a: D) => D): void;
  b(): (a: D) => D;
}

Expected behavior:

no error

Actual behavior:

$ node built/local/tsc.js index.d.ts --noEmit --strictFunctionTypes
index.d.ts(5,15): error TS2415: Class 'D' incorrectly extends base class 'C'.
  Types of property 'a' are incompatible.
    Type '(f: (a: D) => D) => void' is not assignable to type '(f: (a: C) => C) => void'.
      Types of parameters 'f' and 'f' are incompatible.
        Types of parameters 'a' and 'a' are incompatible.
          Type 'D' is not assignable to type 'C'.
            Types of property 'b' are incompatible.
              Type '() => (a: D) => D' is not assignable to type '() => (a: C) => C'.
                Type '(a: D) => D' is not assignable to type '(a: C) => C'.
                  Types of parameters 'a' and 'a' are incompatible.
                    Type 'C' is not assignable to type 'D'.
                      Property 'p' is missing in type 'C'.
@aluanhaddad
Copy link
Contributor

I may well be missing something but it seems that if I were to have

const c: C = new D;

c.a(() => new C);

And if the implementation of D.prototype.a is

a(f: (a: D) => D) {
  const otherD = f(new D);
  this.p = otherD.p;
}

I would say LSP is violated since p is not optional.

@falsandtru
Copy link
Contributor Author

falsandtru commented Oct 7, 2017

I think compiler should throw an error with that assignment const c: C = new D; instead of class extending. However, probably my pr with extending is out of the scope of LSP. So I'll fix this issue.

Another, this error is caused on b method. So compiler doesn't reject your example. It seems to make another issue.

declare class C {
  a(f: (a: C) => C): void;
}
declare class D extends C {
  p: void;
  a(f: (a: D) => D): void; // no error, but should be an error
}

@falsandtru falsandtru changed the title strictFunctionTypes shouldn't prevent method overriding under the Liskov substitution principle strictFunctionTypes shouldn't prevent method overriding Oct 7, 2017
@falsandtru
Copy link
Contributor Author

falsandtru commented Oct 7, 2017

I drop this issue. Thanks @aluanhaddad .

@microsoft microsoft locked and limited conversation to collaborators Jun 14, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants