Microsoft/TypeScript

Type Merging between extends and intersection

Open

#8,606 创建于 2016年5月14日

在 GitHub 查看
 (5 评论) (2 反应) (0 负责人)TypeScript (48,455 star) (6,726 fork)batch import
Effort: ModerateHelp WantedSuggestion

描述

TypeScript Version:

1.8.10

Code

interface Foo {
    on(type: 'foo', listener: (event: MouseEvent) => boolean): boolean;
    on(type: string, listener: (event: Event) => boolean): boolean;
}

interface Bar {
    on(type: 'bar', listener: (event: MSGestureEvent) => boolean): boolean;
    on(type: string, listener: (event: Event) => boolean): boolean;
}

interface FooBarA extends Foo, Bar {} // Error: not correctly extended

interface FooBarB extends Foo, Bar {
    on(type: 'foo', listener: (event: MouseEvent) => boolean): boolean;
    on(type: 'bar', listener: (event: MSGestureEvent) => boolean): boolean;
    on(type: string, listener: (event: Event) => boolean): boolean;
}

type FooBarC = Foo & Bar;

let foobar: FooBarC;

foobar.on('foo', (event) => { return false; });

Expected behavior:

That FooBarA would work instead of throwing an error.

Actual behavior:

FooBarA complains Interface 'FooBarA' cannot simultaneously extend types 'Foo' and 'Bar'. Named property 'on' of types 'Foo' and 'Bar' are not identical.

While that is true in the strictest sense, the "base" override matches, which means in theory the string literal types could be merged and the error should only occur if there is a conflict between a specific string literal type.

Using the intersection type works perfectly fine and the resulting type mirrors the runtime behaviour. Using the "reimplement all methods" (FooBarB) gets really tedious really quickly when you are trying to do something like model event listeners like the above.

贡献者指南