在子类或接口上定义的 Typescript 专用重载

Chr*_*ert 5 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
}
Run Code Online (Sandbox Code Playgroud)

Rya*_*ugh 2

仅当函数重载是对象类型上的调用签名时,它们才会被组合。最简单的修复(对于接口情况)是将函数类型分离到它自己的接口中并扩展它:

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
Run Code Online (Sandbox Code Playgroud)

类情况中的等效版本需要一些工作(假设您关心原型上的函数 - 如果不关心,只需使用函数表达式作为初始化程序on):

class Emitter {
    on: EmitterEvent;
}
module Emitter {
    Emitter.prototype.on = function(name: string, handler: any) {
        // Code here
    }
}
Run Code Online (Sandbox Code Playgroud)