Microsoft/TypeScript

Multiple sets of mutually exclusives properties lead to wrong compiler error

Open

#49,528 创建于 2022年6月13日

在 GitHub 查看
 (1 评论) (0 反应) (0 负责人)TypeScript (6,726 fork)batch import
Experience EnhancementHelp WantedSuggestion

仓库指标

Star
 (48,455 star)
PR 合并指标
 (平均合并 6天 17小时) (30 天内合并 9 个 PR)

描述

Bug Report

🔎 Search Terms

type union interface mutually exclusive property never

🕗 Version & Regression Information

I stumble on it today. Happen in the nightly. Happen from ES3 to ESNext on the playground.

  • This is the behavior in every version I tried, and I reviewed the FAQ for entries about a bug with properties of type never.

⏯ Playground Link

Playground link with relevant code

💻 Code

interface Person
{
    kind: "Person";
    name: string;
}

interface Company
{
    kind: "Company";
    name: string;
}

// Fragments
interface _fromPerson
{
    fromPerson: Person;
    fromCompany?: never;
}

interface _fromCompany
{
    fromPerson?: never;
    fromCompany: Company;
}

interface _toPerson
{
    toPerson: Person;
    toCompany?: never;
}

interface _toCompany
{
    toPerson?: never;
    toCompany: Company;
}

interface RawMessage
{
    timestamp: number;
    title: string;
    content: string;
}

// Combined type
type Message = (
    RawMessage
    & (_fromPerson | _fromCompany)
    & (_toPerson | _toCompany)
);

const MESSAGE: Message = {
    timestamp: 1577836800000,
    title: "Bug",
    content: "This is an example",
    fromPerson: {
        kind: "Person",
        name: "Alice"
    },
    toPerson: {
        kind: "Person",
        name: "Bob"
    },
    toCompany: {
        kind: "Company",
        name: "ACME"
    },
};

🙁 Actual behavior

toPerson and toCompany are mutually exclusive, but the compiler report as error that property fromCompany is missing while fromPerson is already there and mutually exclusive with fromCompany.

(ts2322)
Type '{ ... }' is not assignable to type 'Message'.
  Type '{ ... }' is not assignable to type 'RawMessage & _fromCompany & _toCompany'.
    Property 'fromCompany' is missing in type '{ ... }' but required in type '_fromCompany'.

If you only have 1 set of mutually exclusive interfaces, you get a correct error :

(ts2322)
Type '{ ... }' is not assignable to type 'Message'.
  Type '{ ... }' is not assignable to type 'RawMessage & _toCompany'.
    Type '{ ... }' is not assignable to type '_toCompany'.
      Types of property 'toPerson' are incompatible.
        Type '{ kind: "Person"; name: string; }' is not assignable to type 'never'.

🙂 Expected behavior

The compiler do not mention fromCompany, but mention toPerson and toCompany being mutually exclusive.

(ts2322)
Type '{ ... }' is not assignable to type 'Message'.
  Type '{ ... }' is not assignable to type 'RawMessage & _toCompany'.
    Type '{ ... }' is not assignable to type '_toCompany'.
      Types of property 'toPerson' are incompatible.
        Type '{ kind: "Person"; name: string; }' is not assignable to type 'never'.

贡献者指南