首页 文章

键入可以应用于类和实例的Typescript mixin函数

提问于
浏览
1

TL;DR: 我的函数接受构造函数或构造对象,对其进行变异,然后返回它 . 如何正确键入返回值以使类保持类,对象保留对象,并且两者都具有新属性?

Details

我很接近:当混合到对象中时,原始方法和混合方法都可用,并且当混合到构造函数中时,只有混合方法可用 .

Two problems with my current solution:

  • 混合到构造函数时,生成的实例的类型是 MixinType & typof OriginalClass 而不是 MixinType & OriginalClass (OriginalClass上的静态方法可用作实例方法,并且实例方法不可用

  • 当混合到构造函数中时,构造函数在其类型签名中没有参数,它具有 MixinTypeClass 的构造函数签名(这不是我写的方式 - 's why I' m问这个问题,我正在寻找另一种方法来做它) .

My best attempt

class OriginalClass {
    instanceMethod(): void { }
}

interface MixinType {
    mixedIn(): void;
}

interface MixinTypeClass<T> {
    new (): MixinType & T;
}

function Mixin<T extends Function>(classOrInstance: T): MixinTypeClass<T>;
function Mixin<T extends Object>(classOrInstance: T): T & MixinType;
function Mixin<T extends any>(classOrInstance: T): any {
    if (typeof classOrInstance === 'function') {
        (classOrInstance.prototype as any).mixedIn = () => { }
        return classOrInstance as any as MixinTypeClass<T>;
    } else {
        (classOrInstance as any).mixedIn = () => { }
        return classOrInstance as typeof classOrInstance & MixinType;
    }
}

let NewClass = Mixin(OriginalClass);
let instance1 = new NewClass();
instance1.mixedIn();
// Property 'instanceMethod' does not exist on the type 'MixinType & typeof OriginalClass'
instance1.instanceMethod();

let instance2 = Mixin(new OriginalClass());
instance2.mixedIn();
instance2.instanceMethod();

So, how can I change Mixin so that there is no compiler error for instance1.instanceMethod()?

1 回答

  • 0

    classOrInstance 缩短为简单的 arg ,您可以执行以下操作:

    function Mixin<T extends Object>(arg: Function): MixinTypeClass<T>;
    function Mixin<T extends Object>(arg: T): T & MixinType;
    function Mixin<T extends Object>(arg: Function | T): any {
        if (arg instanceof Function) {
            (arg.prototype as any).mixedIn = () => { }
            return arg as MixinTypeClass<T>;
        } else {
            (arg as any).mixedIn = () => { }
            return arg as T & MixinType;
        }
    }
    

    这提供了完整的智能感知和类型安全:

    let NewClass: MixinTypeClass<OriginalClass> = Mixin<OriginalClass>(OriginalClass);
    let instance1: OriginalClass & MixinType = new NewClass();
    instance1.mixedIn();
    instance1.instanceMethod();
    
    let instance2: OriginalClass & MixinType = Mixin<OriginalClass>(new OriginalClass());
    instance2.mixedIn();
    instance2.instanceMethod();
    

    有趣的是, MixinTypeClass<OriginalClass>OriginalClass & MixinType 不一样 .

相关问题