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

Consider using union types for function return expressions #921

Closed
RyanCavanaugh opened this issue Oct 20, 2014 · 3 comments
Closed

Consider using union types for function return expressions #921

RyanCavanaugh opened this issue Oct 20, 2014 · 3 comments
Labels
Declined The issue was declined as something which matches the TypeScript vision Suggestion An idea for TypeScript

Comments

@RyanCavanaugh
Copy link
Member

Via #919

Even with union types, we still require that a best common type can be selected from the types of the return expressions in a function:

function fn() { // Error, return expressions do not have a BCT
  if(x) {
    return 'foo';
  } else {
    return 42;
  }
}

If this is the desired behavior, the user must write

function fn(): number|string {

This is inconsistent with how we're treating other cases, e.g. var x = [1, 'foo']; produces anArray<number|string>.

Is the desired behavior here that we infer a more complex union type return type for a function, or that we enforce a consistent set of return expression types when no other information is given?

@RyanCavanaugh RyanCavanaugh added Suggestion An idea for TypeScript In Discussion Not yet reached consensus labels Oct 20, 2014
@RyanCavanaugh
Copy link
Member Author

Thoughts on this:

  • Returning a union type is (probably?) much more rare than accepting a union type. We should default to skepticism here.
  • Library authors are often writing functions that don't have any in-program TypeScript callers. Accidentally returning disparate types from a function here won't be obvious unless they examine a .d.ts file, or compile a dependent program. This pushes the bug further down the development pipeline.
  • In the case where a function returns multiple objects, e.g. Cat or Dog, we will infer Cat|Dog when it's likely that the user would have preferred that the return type be Mammal or Animal.

There's also a big danger for functions which intend to return a boolean value. Consider something like this, where you'd never actually use the type in a way that reveals that it's become a union type:

function isUndefinedOrEmpty(s: string) {
  if(s === undefined) {
    return true;
  } else {
    return s.length = 0;
  } 
}

// Later, this isn't an error
if(isUndefinedOrEmpty(n)) { ... }
// This isn't an error either
if(isUndefinedOrEmpty(n) === true) { }

@RyanCavanaugh RyanCavanaugh added Declined The issue was declined as something which matches the TypeScript vision and removed In Discussion Not yet reached consensus labels Apr 21, 2015
@RyanCavanaugh
Copy link
Member Author

Everyone seems to like the current behavior.

@JsonFreeman
Copy link
Contributor

Perhaps we should reconsider this in the context of yield expressions in a generator. Ideally yield expressions should be subject to the same rules as return expressions, with respect to common type / union type. For someone using generators to model async/coroutine style programming, it is quite common to yield several unrelated types from a generator. For context, see #2873 (comment) and #2873 (comment).

Our three options are:

  1. Infer union types for both return and yield expressions
  2. Do not infer union types
  3. Infer union types for yield expressions, but not return expressions.

@microsoft microsoft locked and limited conversation to collaborators Jun 18, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Declined The issue was declined as something which matches the TypeScript vision Suggestion An idea for TypeScript
Projects
None yet
Development

No branches or pull requests

2 participants