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

Contextual typing failure with discriminated type and partially overlapping type. #16513

Closed
yannack opened this issue Jun 14, 2017 · 4 comments
Closed
Assignees
Labels
Bug A bug in TypeScript Duplicate An existing issue was already created

Comments

@yannack
Copy link

yannack commented Jun 14, 2017

TypeScript Version: 2.3 +

Code

type MyType = 'meep'|'bidi';
type ThatType = 'moop'|'meep';

interface Foo {  
  isfoo: 'true';
  foo: MyType;
}
interface Bar {
  isfoo: 'false';
  foo: string;
}

let arr: Array<Foo|Bar>;

arr = [{foo: 'meep', isfoo: 'true'}, 
       {foo: 'moop', isfoo: 'false'}];

Expected behavior: This should compile. The discriminant isfoo should be enough to figure out that the first element of the array can only be a Foo and the second is a Bar.

Actual behavior:
ERROR(15,1): : Type '({ foo: string; isfoo: "true"; } | { foo: string; isfoo: "false"; })[]' is not assignable to type '(Foo | Bar)[]'.
Type '{ foo: string; isfoo: "true"; } | { foo: string; isfoo: "false"; }' is not assignable to type 'Foo | Bar'.
Type '{ foo: string; isfoo: "true"; }' is not assignable to type 'Foo | Bar'.
Type '{ foo: string; isfoo: "true"; }' is not assignable to type 'Foo'.
Types of property 'foo' are incompatible.
Type 'string' is not assignable to type 'MyType'.

However, if Foo's foo is declared as a string, then it compiles fine. If Bar's foo is declared as a ThatType, then it also compiles fine.

@yannack
Copy link
Author

yannack commented Jun 14, 2017 via email

@DanielRosenwasser
Copy link
Member

The first symptom we're seeing is that {foo: 'meep', isfoo: 'true'} is not assignable to Foo.

What we think is happening is that when looking at the type of the foo property, we get the contextual type to decide whether to widen. We see that the contextual type is string | MyType which subtype-reduces to string. So the type of the foo property is widened to string, but at that point it's no longer compatible with Foo.

@DanielRosenwasser DanielRosenwasser added the Bug A bug in TypeScript label Jun 19, 2017
@DanielRosenwasser DanielRosenwasser added this to the TypeScript 2.5 milestone Jun 19, 2017
@sandersn sandersn changed the title Type inference failure with discriminated type and partially overlapping type. Contextual typing failure with discriminated type and partially overlapping type. Aug 16, 2017
@chmln
Copy link

chmln commented Aug 22, 2017

Similarly ran into this issue when typing responses from a database.

I'm aware that the current solution is to employ discriminated type unions with varying string values.
But it doesn't feel right to pollute my schemas and data with unnecessary fields.

interface T {
    _id: string
    revision: number
}

interface Error {
    _id: undefined
    error: string  
}

const getDoc = (s: string): T | Error => {
    if (Math.random() < 0.5) {
        const r: T = {
            _id: "123",
            revision: 1
        }
        return r
    }

    else {
        const e: Error = {
            error: "Not found"
        }
       // Error: property 'name' is missing in type { error: string }
        return e
    }    
}

const doc = (id: string) => {
    const d = getDoc(id)
    if (d._id === undefined) {
        console.log(d.error)
         // 'error' doesnt exist on type 'T'
    }

    else {
        console.log(d.revision)
        // Error: 'revision' doesnt exist on type 'Error'
    }
}

@sandersn
Copy link
Member

sandersn commented Oct 3, 2017

Duplicate of #16457

@sandersn sandersn marked this as a duplicate of #16457 Oct 3, 2017
@sandersn sandersn added the Duplicate An existing issue was already created label Oct 3, 2017
@sandersn sandersn closed this as completed Oct 3, 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
Bug A bug in TypeScript Duplicate An existing issue was already created
Projects
None yet
Development

No branches or pull requests

5 participants