【问题标题】:Class constructor type in typescript?打字稿中的类构造函数类型?
【发布时间】:2017-01-29 13:43:14
【问题描述】:

如何声明class 类型,以确保对象是通用类的构造函数?

在下面的示例中,我想知道应该给AnimalClass 提供哪种类型,以便它可以是PenguinLion

class Animal {
    constructor() {
        console.log("Animal");
    }
}

class Penguin extends Animal {
    constructor() {
        super();
        console.log("Penguin");
    }
}

class Lion extends Animal {
    constructor() {
        super();
        console.log("Lion");
    }
}

class Zoo {
    AnimalClass: class // AnimalClass could be 'Lion' or 'Penguin'

    constructor(AnimalClass: class) {
        this.AnimalClass = AnimalClass
        let Hector = new AnimalClass();
    }
}

当然class类型不行,反正也太笼统了。

【问题讨论】:

    标签: class typescript types constructor


    【解决方案1】:

    编辑:这个问题在 2016 年得到了回答,有点过时了。查看下面的@Nenad 最新答案。

    来自typescript interfaces reference的解决方案:

    interface ClockConstructor {
        new (hour: number, minute: number): ClockInterface;
    }
    interface ClockInterface {
        tick();
    }
    
    function createClock(ctor: ClockConstructor, hour: number, minute: number): ClockInterface {
        return new ctor(hour, minute);
    }
    
    class DigitalClock implements ClockInterface {
        constructor(h: number, m: number) { }
        tick() {
            console.log("beep beep");
        }
    }
    class AnalogClock implements ClockInterface {
        constructor(h: number, m: number) { }
        tick() {
            console.log("tick tock");
        }
    }
    
    let digital = createClock(DigitalClock, 12, 17);
    let analog = createClock(AnalogClock, 7, 32);
    

    所以前面的例子变成了:

    interface AnimalConstructor {
        new (): Animal;
    }
    
    class Animal {
        constructor() {
            console.log("Animal");
        }
    }
    
    class Penguin extends Animal {
        constructor() {
            super();
            console.log("Penguin");
        }
    }
    
    class Lion extends Animal {
        constructor() {
            super();
            console.log("Lion");
        }
    }
    
    class Zoo {
        AnimalClass: AnimalConstructor // AnimalClass can be 'Lion' or 'Penguin'
        
        constructor(AnimalClass: AnimalConstructor) {
            this.AnimalClass = AnimalClass
            let Hector = new AnimalClass();
        }
    }
    

    【讨论】:

    • 我只是想补充一点,这个解决方案对我不起作用,如果你想使用一个带有非零参数的构造函数,它也不起作用。我花了很长时间才弄清楚为什么这个例子有效,但我的代码却没有。经过数小时的搜索,我发现使用AnimalClass: typeof Animal。这将适用于动态加载给定类的子类。
    • @pixelpax 你可以像这样定义一个非零参数构造函数:new (...args: any[]): Animal
    • @pixelpax 但它毫无意义,因为typeof Animal 只是字符串"function"。任何课程都会满足这一点,而不仅仅是动物角色。
    • @arthur.sw,请查看以下链接。它可以工作,但编译器不应该编译最后一行jsfiddle.net/z4vo5u5d/8456
    • Its meaningless though, as typeof Animal is just the string "function" -- 在纯 JS 中,是的。在 TypeScript 类型注释中,没有。 typeof X 表示符号 X 的类型,无论它是什么,并且正在由编译器静态处理。
    【解决方案2】:

    像这样:

    class Zoo {
        AnimalClass: typeof Animal;
    
        constructor(AnimalClass: typeof Animal ) {
            this.AnimalClass = AnimalClass
            let Hector = new AnimalClass();
        }
    }
    

    或者只是:

    class Zoo {
        constructor(public AnimalClass: typeof Animal ) {
            let Hector = new AnimalClass();
        }
    }
    

    typeof Class 是类构造函数的类型。它比自定义构造函数类型声明更可取,因为它可以正确处理静态类成员。

    这是TypeScript docs 的相关部分。搜索typeof。作为 TypeScript 类型注释的一部分,它的意思是“给我一个叫做 Animal 的符号的类型”,在我们的例子中,它是类构造函数的类型。

    【讨论】:

    • typeof返回字符串,不能用结果调用new
    • typeof Animal 是一个 TypeScript 类型注释,它“返回”Animal 构造函数的类型。它不返回字符串。
    • 在 typescript 操场上运行有问题的代码并在尝试更正答案之前查阅文档 (typescriptlang.org/docs/handbook/classes.html) 总是一个好主意。永远不会伤害:)。
    • 比公认的答案更好、更直观!
    • 它不适用于抽象类。
    【解决方案3】:

    如何声明一个类类型,以确保对象是一个通用类的构造函数?

    构造函数类型可以定义为:

     type AConstructorTypeOf<T> = new (...args:any[]) => T;
    
     class A { ... }
    
     function factory(Ctor: AConstructorTypeOf<A>){
       return new Ctor();
     }
    
    const aInstance = factory(A);
    

    【讨论】:

    • 不幸的是,使用这种方法你会丢失构造函数参数的类型检查。
    【解决方案4】:

    当最初提出问题时,我不确定在 TypeScript 中这是否可行,但我首选的解决方案是使用 generics

    class Zoo<T extends Animal> {
        constructor(public readonly AnimalClass: new () => T) {
        }
    }
    

    即使在 TypeScript 智能感知中,变量 penguinlion 也可以推断出具体类型 PenguinLion

    const penguinZoo = new Zoo(Penguin);
    const penguin = new penguinZoo.AnimalClass(); // `penguin` is of `Penguin` type.
    
    const lionZoo = new Zoo(Lion);
    const lion = new lionZoo.AnimalClass(); // `lion` is `Lion` type.
    

    【讨论】:

    猜你喜欢
    • 2019-07-05
    • 2019-04-13
    • 1970-01-01
    • 2017-03-03
    • 1970-01-01
    • 2018-06-08
    • 2020-02-22
    • 2022-01-21
    相关资源
    最近更新 更多