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

Sub-typing issue when referencing a parent entity #30582

Closed
ClementNerma opened this issue Mar 25, 2019 · 5 comments
Closed

Sub-typing issue when referencing a parent entity #30582

ClementNerma opened this issue Mar 25, 2019 · 5 comments
Labels
Working as Intended The behavior described is the intended behavior; this is not a bug

Comments

@ClementNerma
Copy link

TypeScript Version: 3.4.0-dev.201xxxxx

// Get the 'value' from 'obj' and return its approximation
function approximate(obj: A): string {
  return obj.value.toFixed(2);
}

interface A {
  value: number;
}

// In TypeScript, 'B' is (wrongly) considered as a sub-type of 'A'
//  because 'number | string' is a sub-type of 'number'
interface B {
  value: number | string;
}

// Declare an 'A' entity
let a: A = { value: 2 };

// Declare a 'B' one with 'a''s content
let b: B = a;

// Use sub-typing overlapping to change 'a''s 'value'
b.value = 'Hello world!';

// Do the approximation
// This code is perfectly valid and compiles without any error
//  but will fail at runtime because of a type error ('.toFixed' is not a function)
// Even with strict compilation rules
// (noImplicitAny, strictNullChecks, strictFunctionTypes, strictPropertyInitialization, noImplicitThis, noImplicitReturns)
approximate(a);

Expected behavior: Do not compile because b shouldn't be able to be a reference to a. Indeed, B shouldn't be considered as a sub-type of A because number | string does not strictly overlaps number

Actual behavior: Code compiles, and fails at runtime.

Playground Link: https://bit.ly/2U2Cpmz

@DanielRosenwasser
Copy link
Member

DanielRosenwasser commented Mar 25, 2019

In TypeScript, 'B' is (wrongly) considered as a sub-type of 'A'

It's the opposite, but I know what you mean. This is a duplicate of #8474.

@DanielRosenwasser DanielRosenwasser added Duplicate An existing issue was already created and removed Duplicate An existing issue was already created labels Mar 25, 2019
@DanielRosenwasser
Copy link
Member

DanielRosenwasser commented Mar 25, 2019

Actually, it's not quite a duplicate - but it's just that we've made an assumption that mutable properties should be related in a covariant, rather than invariant, manner with respect to their containing types. I don't know if we could realistically fix this.

@ClementNerma
Copy link
Author

In TypeScript, 'B' is (wrongly) considered as a sub-type of 'A'

Yes sorry, that's what I meant ^^

Actually, it's not quite a duplicate - but it's just that we've made an assumption that mutable properties should be related in a covariant, rather than invariant, manner with respect to their containing types. I don't know if we could realistically fix this.

That's a rare scenario for sure, so this problem shouldn't come in many scripts. I don't know how this is implemented in the compiler, so I let you judge this by yourself :)

@RyanCavanaugh RyanCavanaugh added the Working as Intended The behavior described is the intended behavior; this is not a bug label Mar 25, 2019
@RyanCavanaugh
Copy link
Member

Our type system is covariant by default and writing through a supertype alias is the major hole created by that. It's definitely a trade-off.

@typescript-bot
Copy link
Collaborator

This issue has been marked 'Working as Intended' and has seen no recent activity. It has been automatically closed for house-keeping purposes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Working as Intended The behavior described is the intended behavior; this is not a bug
Projects
None yet
Development

No branches or pull requests

4 participants