Skip to content

Returning union of interfaces and conditional parameters #18230

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

Closed
armano2 opened this issue Sep 3, 2017 · 4 comments
Closed

Returning union of interfaces and conditional parameters #18230

armano2 opened this issue Sep 3, 2017 · 4 comments
Labels
Working as Intended The behavior described is the intended behavior; this is not a bug

Comments

@armano2
Copy link

armano2 commented Sep 3, 2017

TypeScript Version: 2.5.2

Code

enum Types {
  TYPE_A = 'TYPE_A',
  TYPE_B = 'TYPE_B',
}

interface ITypeA {
  type : Types.TYPE_A
  variable : string
}

interface ITypeB {
  type : Types.TYPE_B
  variable : string
}

function myFunction (variable : string) : ITypeB | ITypeA {
  const type = (variable === 'A') ? Types.TYPE_A : Types.TYPE_B
  return {
    type,
    variable,
  }
}

Expected behavior:
there should be no type error
Actual behavior:

Type '{ type: Types; variable: string; }' is not assignable to type 'ITypeA | ITypeB'.
  Type '{ type: Types; variable: string; }' is not assignable to type 'ITypeB'.
    Types of property 'type' are incompatible.
      Type 'Types' is not assignable to type 'Types.TYPE_B'.

This code should work same as, because there is no logical distinction between them

function myFunction (variable : string): ITypeB | ITypeA {
  if (variable === 'A') {
    return {
      type: Types.TYPE_A,
      variable,
    }
  } else {
    return {
      type: Types.TYPE_B,
      variable,
    }
  }
}
@ahejlsberg
Copy link
Member

You're asking that we treat types of the form { kind: 'a' | 'b', ... } as assignable to types of the form { kind: 'a', ... } | { kind: 'b', ... }. This is a valid assumption only in the narrow cases of a single property differing and the remaining properties of the object types all being identical. Those situations are rare in practice, which is why we don't to this extra work in the checker right now.

A simple workaround is to replace ITypeA | ITypeB with single declaration:

interface ITypeAB {
  type : Types.TYPE_A | Types.TYPE_B;
  variable : string
}

@armano2
Copy link
Author

armano2 commented Sep 5, 2017

@ahejlsberg i have 86 interfaces some of them with same fields and some with other.

i can't make ITypeAB cus its not going to be valid in rest of checks

@mhegazy mhegazy added the Working as Intended The behavior described is the intended behavior; this is not a bug label Sep 5, 2017
@weswigham
Copy link
Member

weswigham commented Sep 12, 2017

I actually ran into this a lot while working on #18285 - you run into more than you'd expect once you start working with discriminated unions and the fields you pick from them during control flow analysis... and it's frustrating when it happens.

Also, duplicates #12052.

@mhegazy
Copy link
Contributor

mhegazy commented Sep 26, 2017

Automatically closing this issue for housekeeping purposes. The issue labels indicate that it is unactionable at the moment or has already been addressed.

@mhegazy mhegazy closed this as completed Sep 26, 2017
@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

4 participants