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

[Suggestion] --noImplicitUnionWithUndefinded #14070

Closed
masters3d opened this issue Feb 14, 2017 · 8 comments
Closed

[Suggestion] --noImplicitUnionWithUndefinded #14070

masters3d opened this issue Feb 14, 2017 · 8 comments
Labels
Working as Intended The behavior described is the intended behavior; this is not a bug

Comments

@masters3d
Copy link

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

Code

// A *self-contained* demonstration of the problem follows...
// --strictNullChecks: true

thisFunc() { // implicit type of string | undefined
    const myDict  = new Map<number, string>();
    return myDict.get(10); //(method) Map<number, string>.get(key: number): string | undefined
}

Expected behavior:

Being able to tell the compiler to warn on union types which contain Undefined.

This is from the 2.2 dev Whats New Section:
"Note that the union type case only only occurs in --strictNullChecks mode because null and undefined disappear from unions in classic type checking mode."

In the case of the above code, I know why that is retuning string | undefined but I want the compiler to complain that I am implicitly setting that function to a union with undefined.

Another option is to warn when even I make something implicitly a union.
--noImplicitUnion
I actually don't mind unions just the ones that are undefined even behind the nulls check flag.

Actual behavior:

implicit type of string | undefined

@RyanCavanaugh
Copy link
Member

This seems like a really odd thing to make an error. There's nothing inherently wrong about making a union with undefined and it's not at all obvious why anyone would need to avoid it on purpose, or why the fact that it's implicit even matters.

Maybe some context about what problem led you to this solution would be clarifying.

@masters3d
Copy link
Author

I am picking up TS to use with react native. I posted this question on stackoverflow and somebody suggested that I should use an Option type. I really like option types and I have used them in Swift because they are part of the language but I am not suggestion to add them to TS. In my config I have -noImpliticAny which I've found to be extremely useful and makes my code more readable. I was surprised how many times I was returning union types with undefined since I much rather handle the undefined case with in the function instead of leaking that out of the function. Perhaps it is the fact that I am used to having to deal with Option types which makes me want to be explicit about exposing undefined.

@masters3d
Copy link
Author

This seems like a really odd thing to make an error.

I was actually thinking of making it a warning. Related: #6802

@blakeembrey
Copy link
Contributor

blakeembrey commented Feb 14, 2017

@masters3d You could specify the return type yourself to make it error when the return is not correct: thisFunc (): string {}. Is that the issue? For asserting that it's definitely non-null, you can also do map.get('x')!.

@masters3d
Copy link
Author

@blakeembrey I could specify the return type which I do often. This is in the same vain as noImplicitAny in my opinion.
In the case of "any", I don't necessarily want to specify all the types, just the ones where they are implicitly any.
In the case of T | undefined, I don't want to necessarily have to specify all the return types, just the ones that contain undefined.

@RyanCavanaugh RyanCavanaugh added the Needs Investigation This issue needs a team member to investigate its status. label May 24, 2017
@tekerson
Copy link

I have another scenario that I believe is related (i.e. implicit union with bottom) though not exactly the same. Given this code:

function first<T>(left: T, _right: T): T {
  return left
}

const one = first('one', null)
console.assert(one === 'one')

I expected (and would like) the call to first to be a compile error since the left and right parameters aren't the same type (at least as I would read the type variable). But instead the type variable is inferred to be the more general string | null.

I understand this behavior by default, but strictNulls is described as:

In strict null checking mode, the null and undefined values are not in the domain of every type and are only assignable to themselves and any...

And, I don't believe a type variable should implicitly fall into those assignable types. Also, the sum type is not inferred for non-bottom values. e.g. first('one', 2) is a type error; it doesn't get inferred as string | number.

@gcnew
Copy link
Contributor

gcnew commented Jul 21, 2017

IMHO type variables should never be inferred as a union type, unless there is "evidence" for the union, e.g. a parameter that has the union explicitly provided. A related issue to @tekerson's is #16107.

@RyanCavanaugh RyanCavanaugh added Working as Intended The behavior described is the intended behavior; this is not a bug and removed Needs Investigation This issue needs a team member to investigate its status. labels Sep 16, 2019
@RyanCavanaugh
Copy link
Member

The current rules around when union types are inferred were derived from trying to break only the right amount of code; there aren't any meaningful changes we could make at this point. Without a clearer definition and motivating scenario for OP's flag, there's nothing actionable here.

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

5 participants