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

时间:2017-02-01 00:09:30

标签: typescript

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

详情

我关闭:当混合到对象中时,原始方法和混合方法都可用,并且当混合到构造函数中时,只有混合方法可用。

我目前的解决方案有两个问题:

  1. 当混合到构造函数中时,生成的实例的类型是MixinType & typof OriginalClass而不是MixinType & OriginalClass(OriginalClass上的静态方法可用作实例方法,而实例方法不是{&1;可用
  2. 当混合到构造函数中时,构造函数在其类型签名中没有参数,它具有MixinTypeClass的构造函数签名(这并不令人惊讶,这就是我写它的方式 - 这就是为什么我要问这个问题,我正在寻找另一种方法来做这件事。
  3. 我最好的尝试

    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();
    

    那么,如何更改Mixin以便instance1.instanceMethod()没有编译器错误?

1 个答案:

答案 0 :(得分:0)

var org = [ {name:"one",age:1} ,{name:"two",age:2} ] ; var newArray = org .map( (x,index)=> index === 1 ?Object.assign( {} ,x ,{name:"new name"} ) :x ) ; 缩短为简单的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>并不相同。