Skip to content

Interface type coercion fails with unsatisfied properties in unions #59716

Open
@mio-moto

Description

@mio-moto

🔎 Search Terms

interface type coercion
type coercion
unsatisfied union constraints
property missing in but required
conditional interference

🕗 Version & Regression Information

  • This is the behavior in every version I tried, and I reviewed the FAQ for entries about type coercion

⏯ Playground Link

https://www.typescriptlang.org/play/?#code/JYOwLgpgTgZghgYwgAgILIN4Chm+QZ0gAcAuZARiwF8stRJZEUAhTHPQiU5AJmtvrR4SZMwD6AUQAeYZBBkQQAE3yi2eAsTJ8N8sFDj4yAIgBu0AJ7IEAexsAbY-yxgLRFAGViyALwVkAD68Lm4oAMI2IPgArgC20L5ogcgAFKxB4tJgAJQA3LS2UbIw0SAIiSnZZF5cvgB8yACycGAAFgB0Bso2sZXIDQAM7QCsyAD8vMhk5PmFhNaRMfFQFQDurS0Q5lBkEVFx0Nn1mMg0BYuynESJJWWV+VgA9I-IgKDkyKs2UADW+HQwKSuvh8fnIR2wGjmBygKQwmlqVGy1Dk9nwKAheChy1h8OuiOcz2QgBlyZDwYCorBY6A4oGIoA

💻 Code

interface A {
    step: 1
}

interface B {
    step: 2
}

interface B_Ext extends B {
    step: 2
    extras: "very cool"
}

type Step = 1 | 2
type Consumer = A | (B | B_Ext);

const func = (): Step => Math.random() > 0.5 ? 2 : 1;
const consumer = (whatever: Consumer) => { }


const step = func();

// ✅ works
if(step === 1) {
    consumer({ step })
} else {
    consumer({ step })
}

// ❌ fails
consumer({ step })

🙁 Actual behavior

The compiler expects that all properties of a sub-constituent be satisfied

🙂 Expected behavior

The union defines that it is either A | B and B might be B or B & Extras

Additional information about the issue

The same happens with types instead of interfaces as well as a the extras being passed as union of the type:

// causes the same issues
type A = { step: 1 }
type B = { step: 2 } & ({} | { extras: 'very good' })

Metadata

Metadata

Assignees

No one assigned

    Labels

    BugA bug in TypeScriptHelp WantedYou can do this

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions