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

ternary type inference is wrong #16870

Closed
Spongman opened this issue Jun 30, 2017 · 4 comments
Closed

ternary type inference is wrong #16870

Spongman opened this issue Jun 30, 2017 · 4 comments
Labels
Working as Intended The behavior described is the intended behavior; this is not a bug

Comments

@Spongman
Copy link

TypeScript Version: 2.4.0 / nightly (2.5.0-dev.201xxxxx)

Code

class Base { }
class Derived1 extends Base { }
class Derived2 extends Base { }

var t1 = (Math.random() < 0.5) ? "asdasd" : 34;
// t1: string | number

var t2 = (Math.random() < 0.5) ? new Derived1() : new Derived2();
// t2: Derived1

Expected behavior:

// t2: Derived1 | Derived2

I understand the shapes are the same, but this means the runtime types don't match up with the static type.

@kitsonk
Copy link
Contributor

kitsonk commented Jun 30, 2017

TypeScript uses a structural type system. To TypeScript, an instance of Derived1 and Derived2 look the same, so as it infers the type, it sees that there is no structural difference between Derived1 and Derived2 and so doesn't create a union.

Here, there is a structural difference between the two types, so you get what you expect:

class Base { }
class Derived1 extends Base {
	foo = 'bar'
}
class Derived2 extends Base {
	bar = 1
}

var t1 = (Math.random() < 0.5) ? "asdasd" : 34;
// t1: string | number

var t2 = (Math.random() < 0.5) ? new Derived1() : new Derived2();
// t2: Derived1 | Derived 2

JavaScript behaves in a structural way in everything except the instanceof operator. The discussion of some sort of nominal typing support for TypeScript is covered in issue #202 (as well as loads of other information on the subject).

@Spongman
Copy link
Author

there is no structural difference between Derived1 and Derived2

really? (new Derived1()).constructor !== (new Derived2()).constructor

@RyanCavanaugh RyanCavanaugh added the Working as Intended The behavior described is the intended behavior; this is not a bug label Jun 30, 2017
@RyanCavanaugh
Copy link
Member

@kitsonk
Copy link
Contributor

kitsonk commented Jul 1, 2017

really? (new Derived1()).constructor !== (new Derived2()).constructor

And for the record, those are pointers to functions that ermmm have the same structure... This is, I am afraid, basic TypeScript concepts.

@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
Working as Intended The behavior described is the intended behavior; this is not a bug
Projects
None yet
Development

No branches or pull requests

3 participants