简体   繁体   English

如何从 TypeScript 中的模板扩展摘要 class?

[英]How to extends abstract class from template in TypeScript?

I have an architecture like that and I want to extends my TemplateService with a template but actually I have an error on it.我有一个这样的架构,我想用一个模板扩展我的TemplateService但实际上我有一个错误。 Is there a way to extends an abstract class from a template?有没有办法从模板扩展抽象 class?

// Error message
ReferenceError: Service is not defined
abstract class TemplateService<Service> extends Service
                                               ^
// My code
abstract class TemplateService<Service> extends Service { // Cannot find name 'Service'.
    constructor() {
        const name = "Hello world !";

        super(name);
    }

    public getJob(): string {
        return "Job";
    }

    protected getAge(): number {
        return 25;
    }
}

class ImportedService {
    constructor(private _name: string) {}

    public getName() {
        return this._name;
    }
}

class MyService extends TemplateService<ImportedService> {
    constructor() {
        super();
    }

    public fooMethod(): void {
        ...
    }
}

It is a category error to write写是类别错误

abstract class TemplateService<Service> extends Service {}

TypeScript's static type system, including generic type parameters, is erased from the emitted JavaScript that actually runs. TypeScript 的 static 类型系统,包括泛型类型参数,从实际运行的发出的 JavaScript 中删除 In the above, abstract and <Service> are part of the static type system, while the rest is valid JavaScript (at least for modern versions of JavaScript).在上面, abstract<Service>是 static 类型系统的一部分,而 rest 是有效的 JavaScript(至少对于现代版本的 JavaScript)。 Your code as written would be emitted to something like您编写的代码将被发送到类似

class TemplateService extends Service {}

which hopefully shows the problem.希望能说明问题。 Unless there happens to be a class constructor named Service in scope, this would be a runtime error.除非 scope 中恰好有一个名为Service的 class 构造函数,否则这将是一个运行时错误。 You can't subclass a type ;你不能子类化一个类型 you need to subclass a constructor value .您需要子类化构造函数值


TypeScript has some support for subclassing an arbitrary constructor value via the concept of mixins . TypeScript 对通过mixins的概念对任意构造函数值进行子类化提供了一些支持。 Instead of writing TemplateService as a class, you make it a class factory function that accepts a class constructor as an input.不是将TemplateService编写为 class,而是将其设为 class工厂 function ,它接受 class 构造函数作为输入。 Conceptually it would look like从概念上讲它看起来像

// don't write this, it's not valid TS
function TemplateService<C extends new (name: string) => object>(ctor: C) {
    return class extends ctor {  // error!
// ------> ~~~~~
        constructor() {
            const name = "Hello world !";
            super(name);
        }
        public getJob(): string {
            return "Job";
        }

        protected getAge(): number {
            return 25;
        }
    };
}

And you'd use it like你会像这样使用它

class ImportedService {
    constructor(private _name: string) { }

    public getName() {
        return this._name;
    }
}

class MyService extends TemplateService(ImportedService) {
    constructor() {
        super();
    }

    public fooMethod(): void {
        console.log(this.getName());
        console.log(this.getJob());
        console.log(this.getAge())
    }
}

Unfortunately, TypeScript's mixin support assumes that you are going to just pass the constructor parameters through, so the above TemplateService implementation gives compiler errors.不幸的是,TypeScript 的 mixin 支持假定您将只传递构造函数参数,因此上面的TemplateService实现会产生编译器错误。 There are open issues about this, such as microsoft/TypeScript#37142 .有关于此的未解决问题,例如microsoft/TypeScript#37142 For now all I could say is to work around it by using several type assertions to trick the compiler into allowing the mixin and into to giving it the correct type.现在我能说的就是通过使用几个类型断言来欺骗编译器允许 mixin 并给它正确的类型来解决它。

For the particular example code here, it could look like:对于此处的特定示例代码,它可能如下所示:

function TemplateService<C extends new (name: string) => object>(ctor: C) {
    const c = class extends (ctor as new (...args: any) => object) {
        constructor() {
            const name = "Hello world !";
            super(name);
        }
        public getJob(): string {
            return "Job";
        }

        protected getAge(): number {
            return 25;
        }
    };

    return c as {
        new(): InstanceType<C> & InstanceType<typeof c>;
    }
}

Now the compiler believes that TemplateService(ImportedService) is a no-arg constructor which produces instances of a combination (via intersection ) of ImportedService and the type of the anonymous class expression with a getJob() method and protected getAge() method.现在编译器认为TemplateService(ImportedService)是一个无参数构造函数,它生成ImportedService的组合实例(通过交集)和匿名 class 表达式的类型以及getJob()方法和protected getAge()方法。

Playground link to code 游乐场代码链接

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 在 TypeScript 类中声明事件,该类扩展了扩展 EventEmitter 的抽象类 - Declaring events in a TypeScript class which extends an abstract class that extends EventEmitter 如何将变量的类型声明为从打字稿中的基类继承/扩展的类? - How to declare a variable's type as class that inherits/extends from a base class in typescript? Typescript 类从其他类扩展不能用作接口属性 - Typescript class extends from other class cannot be used as interface attributes 如何使用 jest 在 typescript 中测试抽象 class? - How to use jest for testing abstract class in typescript? 如何在 Javascript/Typescript 中将代码从同步和异步类概括为抽象类 - How to generalize code from a sync and an async class to an abstract class in Javascript/Typescript 动态扩展打字稿注释中的类 - Dynamic extends class in a typescript annotation TypeScript + 实体 JS 抽象 Class - TypeScript + Solid JS Abstract Class 如何在抽象父 class 中创建通用方法以实现 typescript? - how make a generic method in a abstract parent class for implementation typescript? 如何在 TypeScript 中使用抽象 class 作为 React 组件的类型? - How to use an abstract class as the type of a React component in TypeScript? TypeScript中的扩展如何工作? - How does extends in TypeScript work?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM