1

我对 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);

游乐场链接

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

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

游乐场链接

正如您在操场上看到的那样,这有错误:

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

rest 参数必须是数组类型。

有没有办法让这个更短、更简单的声明工作?

4

1 回答 1

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)
于 2018-08-02T13:55:03.243 回答