Skip to content
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

Literal type initialization with inheritance #10484

Closed
jods4 opened this issue Aug 22, 2016 · 5 comments
Closed

Literal type initialization with inheritance #10484

jods4 opened this issue Aug 22, 2016 · 5 comments
Labels
Duplicate An existing issue was already created

Comments

@jods4
Copy link

jods4 commented Aug 22, 2016

TypeScript Version: nightly (2.1.0-dev.20160822)

Code

class A {
 protected x: "a" | "b";
}

class B extends A {
  protected x = "b";
}

Expected behavior: Should compile without error. Code seems intuitive to me.

Actual behavior: error TS2415: Class 'B' incorrectly extends base class. Type 'string' is not assignable to type '"a" | "b"'.

@sandersn
Copy link
Member

We tried this a while back, but failed to find a good solution. #6118 gives the result of that work.

Proposals are welcome to fix this problem.

@sandersn
Copy link
Member

Duplicate of #3667. The best place to put a proposal is on #6118 if it's simple or in a new issue if it's not.

@sandersn sandersn added the Duplicate An existing issue was already created label Aug 22, 2016
@jods4
Copy link
Author

jods4 commented Aug 23, 2016

@sandersn I read your comment about RWC. It seems the main issue is lack of variance contract for members of classes. Typing a property with a narrower type in a derived class is OK if your code only reads from the base class but possibly broken if you also write. And there is no way to know this.

In a greenfield there are easy way to fix this, but of course they break existing code 👎 .
Given the constraints, I don't see a good easy solution to make it work + make it backward compatible.

Only thing that comes to mind is a compiler flag 😦
The benefits are important though. Here are some annoyances that I encounter on a daily basis:

  • The example above, where assigning a string to a literal type fails.
  • Typing empty arrays! In a derived class or interface or literal parameter, xs = [] fails and is annoying as hell.
  • Implicitly typed lambda parameters!
  • Bugs because overrides are not properly checked at all.

Some of those are so frequent that I would love even a partial fix, e.g. the empty array initializer and implicitely typed lambdas. Those should be doable with backward compatibility, I think?

@sandersn
Copy link
Member

At this point we're starting to consider patchwork fixes instead of a general fix. @DanielRosenwasser and I were going to get together soon to brainstorm some way to make partial fixes easy to explain if not completely consistent.

In order of likelihood, this is what I'm thinking we would be able to solve:

  1. Overrides without type annotations — otherwise you don't invoke contextual typing. (Modifying contextual typing to work with partial annotations is another big, separate problem complicated primarily by the interaction of contextual typing of lambdas while doing type parameter inference).
  2. Empty arrays assigned to an overridden property.
  3. Un-annotated lambdas assigned to an overridden property. This one seems like the same thing as overridden methods, but they are treated differently by the compiler in some ways.
  4. Typing string literals/null/undefined. There is a long tail of problems that are harder to solve and also have less value. (a property p = null gives you p: any which degrades checking but is otherwise benign).

Unfortunately, the deeper you go on the list, the more of a random bag of patches it becomes. I'm not sure of a solution for that either.

@jods4
Copy link
Author

jods4 commented Aug 23, 2016

@sandersn It is a good list!
I think all my main offenders are on it, thanks! 👏

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Duplicate An existing issue was already created
Projects
None yet
Development

No branches or pull requests

2 participants