2015-02-24 72 views
4

有没有一种方法可以在不需要简单地调用超类或不必要地重复非专用签名的子类中定义实现的情况下进行以下工作?在子类或接口上定义的Typescript专用重载

class Emitter { 
    on(name: 'one', handler: (value: number) => void): void; 
    on(name: string, handler: (...args: any[]) => void): void; 
    on(name: string, handler: (...args: any[]) => void): void { 
     // do stuff 
    } 
} 


class Subclass extends Emitter { 
    on(name: 'two', handler: (value: string) => void): void; 
    on(name: string, handler: (...args: any[]) => void): void; 
    // error no implementation specified 
} 


interface IEmitter { 
    on(name: 'one', handler: (value: number) => void): void; 
    on(name: string, handler: (...args: any[]) => void): void; 
} 


interface ISubclass extends IEmitter { 
    on(name: 'two', handler: (value: string) => void): void; 
    // error overload not assignable to non specialized 
} 

回答

3

函数重载只有在对象类型是调用签名时才会合并。 (该接口的情况下),最简单的解决方法是功能类型划分为不同的自己的接口和扩展:

interface EmitterEvent { 
    (name: 'one', handler: (value: number) => void): void; 
    (name: string, handler: (...args: any[]) => void): void; 
} 

interface SubclassEmitterEvent extends EmitterEvent { 
    (name: 'two', handler: (value: string) => void): void; 
} 

interface IEmitter { 
    on: EmitterEvent; 
} 

interface ISubclass extends IEmitter { 
    on: SubclassEmitterEvent; 
} 

var x: ISubclass; 
x.on('one', n => n.toFixed()); // n: number 
x.on('two', s => s.substr(0)); // s: string 
var y: IEmitter; 
y.on('two', a => a); // a: any 

在类案件的等效版本需要一些工作(假设你关心的功能怎么回事原型 - 如果没有,只使用一个函数表达为一个初始化为on代替):

class Emitter { 
    on: EmitterEvent; 
} 
module Emitter { 
    Emitter.prototype.on = function(name: string, handler: any) { 
     // Code here 
    } 
} 
+0

感谢瑞安!这种方法是可行的,但与在接口上声明方法重载(ala addEventListener)非常不同。有没有可能未来版本的TypesScript将允许类的方法重载来重用基类实现(假设它是兼容的)? – 2015-02-25 02:34:28

+1

不太可能,因为这可能需要一些新的语法或重大更改。 – 2015-02-25 05:23:56

+0

函数在原型上运行的版本有一个缺点,函数不能调用同一类中的其他私有函数。 – 2017-04-27 11:37:37

0

似乎与TS 1.5模块特技(现在被称为一个命名空间)不会工作,因为它抱怨'这个'。

下文一个工作方法我使用的:

interface EventEmitterOn { 
    (event: string, listener:() => void); 
} 

interface FooEventEmitterOn extends EventEmitterOn { 
    (event: 'dependency', listener: (dep: string[]) => void); 
} 

class EventEmitter { 
    on: EventEmitterOn; 
} 

EventEmitter.prototype.on = function(event, listener) { 
    // implementation 
} 

class Foo extends EventEmitter { 
    on: FooEventEmitterOn; 
} 

var foo = new Foo 
// error 
foo.on('dependency', function(dep: number) {}) 
// ok 
foo.on('dependency', function(dep: string[]) {})