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

inference around undefined #6299

Closed
zpdDG4gta8XKpMCd opened this issue Dec 30, 2015 · 2 comments
Closed

inference around undefined #6299

zpdDG4gta8XKpMCd opened this issue Dec 30, 2015 · 2 comments
Labels
Question An issue which isn't directly actionable in code

Comments

@zpdDG4gta8XKpMCd
Copy link

It's given that the Undefined type cannot be referenced. This leads to some interesting observations

let a = undefined;                            // any, unless implicit any is disabled
type B = typeof undefined;                    // B is `any` without a warning and regardless of what you think implicit any is
let b : B;                                    // any
let c = Math.random() > 0.5 ? b : '';         // any
let d = Math.random() > 0.5 ? undefined : ''; // string
let e = Math.random() > 0.5 ? <any>'' : '';   // any

function fn() { return undefined; }           // problem unless implicit any is allowed
let f = Math.random() > 0.5 ? fn() : '';      // any

Basically turns out that undefined is a literal without any type assigned (so is null), despite being a variable in a non-strict mode.

The following case is extremely useful in practice

 let d = Math.random() > 0.5 ? undefined : ''; // string

Because instead of finding the common denominator type the inference craves a type for the "undefined" branch from the expression context. I wish it was the case for the following too, wouldn't you?

function f<r>(): r { return undefined; }
let d = Math.random() > 0.5 ? f() : ''; // {} 

I would be grateful if someone from the design team shared some insights why it is this way, or gave a link that sorts it all out.

@ahejlsberg
Copy link
Member

The undefined and null types are only used for intermediary results in expressions. There is no way to name them, and we perform widening (i.e. conversion to the any type) in places where we might infer the undefined and null types. This is by design as you'd be able to do practically nothing with values and variables of those types.

That said, we have discussed not widening function result types (e.g. here), but it is not without complications.

@DanielRosenwasser
Copy link
Member

To answer your last question...

function f<r>(): r { return undefined; }
let d = Math.random() > 0.5 ? f() : ''; // {} 

this doesn't necessarily have anything to do with inference on undefined. This example is a problem because f() gives you the {} type which is a supertype of string. We then try to reduce the union of this conditional expression {} | string to {}.

For the same reason in the following example

 let d = Math.random() > 0.5 ? undefined : ''; // string

we don't immediately widen the type of undefined, so you get undefined | string, which reduces to string.

I think #360 should be reopened.

@DanielRosenwasser DanielRosenwasser added the Question An issue which isn't directly actionable in code label Dec 31, 2015
@mhegazy mhegazy closed this as completed Feb 20, 2016
@microsoft microsoft locked and limited conversation to collaborators Jun 19, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Question An issue which isn't directly actionable in code
Projects
None yet
Development

No branches or pull requests

4 participants