从typescript中的Generic Type调用Generic Type的静态函数

时间:2018-01-01 03:15:34

标签: typescript generics

我在服务类中有一个函数,它传递了扩展我的Bean类的泛型类型。我希望函数在Bean类中调用静态函数来创建Beans数组。我在操场上的代码编译,但是我得到了

的运行时浏览器错误
Uncaught TypeError: ctor.constructor.fromEntryList is not a function

如果我删除.constructor我得到了创建的bean数组,但是有一个没有.constructor的打字稿错误。

我迷失了如何正确地打字编码这个功能。任何帮助都非常感谢,因为我在SO上找不到先前的答案。

代码:

// Base class that will be extended
class Bean {
    id: number;

    static fromEntryList<T1>(ctor: new (p: number) => T1, numbers: Array<number>): Array<T1> {

        let result: Array<T1> = [];
        for (let anumber of numbers) {
            result.push(new ctor(anumber));
        }
        return result;
    }


    constructor(p: number) {
        this.id = p;
    }
}

// Base service class that will be extended
class BeanService {


    constructor() { }

    get_entry_list<T extends Bean>(ctor: new (p: number) => T): T[] {
        let x: T[] = (<typeof Bean>ctor.constructor).fromEntryList(ctor, [1, 2, 3, 4]);
        return x;
    }
}

let service = new BeanService();
let beans: Bean[] = service.get_entry_list(Bean);

code in playground

感谢。

1 个答案:

答案 0 :(得分:2)

get_entry_list的param定义中,它只定义了ctor的类型但缺少静态方法接口,因此访问它会引发编译错误,而运行时可以正确地访问这些属性。

您可以定义构造函数接口,

interface XXX<T> {
  new(p: number): T;
  fromEntryList<U>(ctor: new (p: number) => U, numbers: Array<number>): Array<U>;
}

基本上是Bean的表示,然后将其用于param的签名

get_entry_list<T extends Bean>(ctor: XXX<T>): Array<T>

允许get_entry_list中提供的ctor可以访问静态方法。

游乐场:

https://www.typescriptlang.org/play/#src=%2F%2F%20Base%20class%20that%20will%20be%20extended%0D%0Aclass%20Bean%20%7B%0D%0A%20%20id%3A%20number%3B%0D%0A%0D%0A%20%20static%20fromEntryList%3CT1%3E(ctor%3A%20new%20(p%3A%20number)%20%3D%3E%20T1%2C%20numbers%3A%20Array%3Cnumber%3E)%3A%20Array%3CT1%3E%20%7B%0D%0A%0D%0A%20%20%20%20%20%20let%20result%3A%20Array%3CT1%3E%20%3D%20%5B%5D%3B%0D%0A%20%20%20%20%20%20for%20(let%20anumber%20of%20numbers)%20%7B%0D%0A%20%20%20%20%20%20%20%20%20%20result.push(new%20ctor(anumber))%3B%0D%0A%20%20%20%20%20%20%7D%0D%0A%20%20%20%20%20%20return%20result%3B%0D%0A%20%20%7D%0D%0A%0D%0A%0D%0A%20%20constructor(p%3A%20number)%20%7B%0D%0A%20%20%20%20%20%20this.id%20%3D%20p%3B%0D%0A%20%20%7D%0D%0A%7D%0D%0A%0D%0Ainterface%20XXX%3CT%3E%20%7B%0D%0A%20%20new(p%3A%20number)%3A%20T%3B%0D%0A%20%20fromEntryList%3CU%3E(ctor%3A%20new%20(p%3A%20number)%20%3D%3E%20U%2C%20numbers%3A%20Array%3Cnumber%3E)%3A%20Array%3CU%3E%3B%0D%0A%7D%0D%0A%0D%0A%2F%2F%20Base%20service%20class%20that%20will%20be%20extended%0D%0Aclass%20BeanService%20%7B%0D%0A%0D%0A%0D%0A%20%20constructor()%20%7B%20%7D%0D%0A%0D%0A%20%20get_entry_list%3CT%20extends%20Bean%3E(ctor%3A%20XXX%3CT%3E)%3A%20Array%3CT%3E%20%7B%0D%0A%20%20%20%20%20%20let%20x%3A%20T%5B%5D%20%3D%20ctor.fromEntryList(ctor%2C%20%5B1%2C%202%2C%203%2C%204%5D)%3B%0D%0A%20%20%20%20%20%20return%20x%3B%0D%0A%20%20%7D%0D%0A%7D%0D%0A%0D%0Alet%20service%20%3D%20new%20BeanService()%3B%0D%0Alet%20beans%3A%20Bean%5B%5D%20%3D%20service.get_entry_list(Bean)%3B%0D%0A%0D%0Aconsole.log(beans)%3B