在Typescript 3.0中创建带有类型检查参数的工厂

时间:2018-08-02 13:18:32

标签: typescript typescript3.0

我对TS 3.0中的新可提取参数列表感到非常兴奋,作为一种学习其工作方式的方法,我想创建一个工厂。

我已经开始工作了

class MyClass{
    constructor(paramOne: string, paramTwo: number, paramThree?: boolean) {

    }
}

class Factory<T extends new (...args: any[]) => any>{

    constructor(private constr: T) { }

    create(...params: T extends new (...args: infer P) => infer R ? P : never): T extends new (...args: infer P) => infer R ? R : never{
        return new this.constr(...params);
    }
}

const myFactory = new Factory(MyClass);

const instance = myFactory.create("hello", 55);

Playground Link

这很酷,但是create()函数的定义有点长,并且包含一定数量的重复项。我试图简化这一点:

create: T extends new (...args: infer P) => infer R ? (...args: P) => R : never = (...params: P) => {
    return new this.constr(...params);
}

Playground Link

您在操场上看到的错误有:

  

类型'(... params:any)=> any'不能分配给类型'T扩展new(... args:infer P)=>推断R吗? (... args:P)=> R:从不。

  

rest参数必须是数组类型。

有没有一种方法可以使此声明更短,更简单?

1 个答案:

答案 0 :(得分:0)

在某些类型参数未知的情况下将值分配给条件类型通常是有问题的,因此我不会走这条路线。

为简化签名,我将使用预定义的InstanceType类型并定义一个特殊类型以提取构造函数参数

class MyClass{
    constructor(paramOne: string, paramTwo: number, paramThree?: boolean) {

    }
}

type ConstructorArguments<T> = T extends new (...args: infer P) => any ? P : never

class Factory<T extends new (...args: any[]) => any>{

    constructor(private constr: T) { }

    create(...params: ConstructorArguments<T> ): InstanceType<T>{
        return new this.constr(...params);
    }
}

const myFactory = new Factory(MyClass);

const instance = myFactory.create("hello", 55)