首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >在用ES6装饰器扩展TypeScript类时扩展类型

在用ES6装饰器扩展TypeScript类时扩展类型
EN

Stack Overflow用户
提问于 2019-02-26 19:03:05
回答 3查看 8.4K关注 0票数 15

我试图用装饰器来装饰一个类(a-la角样式),并向它添加方法和属性。

这是我的示例装饰类:

代码语言:javascript
运行
复制
@decorator
class Person{

}

这位是装饰师:

代码语言:javascript
运行
复制
const decorator = (target)=>{
    return class New_Class extends target {
        myProp:string
    }
}

但是myProp并不是一个已知的人的财产:

代码语言:javascript
运行
复制
person.myProp //Error - myProp does not exist on type Person

如何装饰一个打字本类并保存类型完成、类型安全等?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2019-02-27 10:52:21

为了补充jcalz响应,回到装饰图案的定义,它不会更改其目标的接口/契约。这不仅仅是术语。TypeScript装饰器与Java注释和.NET属性有相似之处,它们与不改变接口的事实相一致:它们只是添加元数据。

课堂混音是一个很好的候选人解决你的问题。但最好不要在名称中使用“装潢师”,以避免混淆。

票数 5
EN

Stack Overflow用户

发布于 2019-04-04 16:16:54

我找到了一种实现多种遗产的解决方案(实际上是对它的级联),但值得一看。

假设您有一个具有以下属性和方法的类库:

代码语言:javascript
运行
复制
class Base {
    tableName = 'My table name';
    hello(name) {
     return `hello ${name}`;
    }
}

您需要一个类来扩展Base,但是您也定义了一些要重用的属性。为此,将执行以下功能:

代码语言:javascript
运行
复制
type Constructor<T = {}> = new (...args: any[]) => T;
function UserFields<TBase extends Constructor>(Base: TBase) {
    return class extends Base {
        name: string;
        email: string;
    };
}

现在,我们可以做一个扩展Base和扩展UserFields的类,类型记录语言服务将从这两个类中找到属性。它模仿多个传统,但它实际上是一个级联。

代码语言:javascript
运行
复制
class User extends UserFields(Base) { }
const u = new User();
u.tableName = 'users'; // ok
u.name = 'John'; // ok

通过这种方式,您可以在任何其他类中重用UserFields函数。这方面的一个明确示例是,如果您希望将客户端的用户对象公开为“干净”对象,并且有可用的字段,那么您就有一个连接到数据库的UserDb对象,而任何其他服务器端方法也可以具有相同的字段。我们只定义了一次数据库字段!

另一件好事是,您可以将mixin1(mixin2.(Base))链接起来,以便在同一个类中拥有尽可能多的属性。

每个人都希望装饰者的属性可以通过类型记录来显示,但同时也是一个很好的解决方案。

票数 8
EN

Stack Overflow用户

发布于 2019-02-26 19:13:29

有一个有很多讨论的关于这一点的GitHub问题。我认为它的总结是:装饰师不会改变class的类型(大部分讨论是关于它是否应该这样做),因此您不能按照您想要的方式来做,如下所示:

代码语言:javascript
运行
复制
const decorator = (target: new (...args: any) => any) => {
  // note I'm extending target, not Person, otherwise you're not
  // decorating the passed-in thing
  return class New_Class extends target {
    myProp!: string
  }
}

@decorator
class Person {
  noKnowledgeOfMyProp: this['myProp'] = "oops"; // error
}

declare const p: Person;
p.myProp; // error, uh oh

您可以做的只是使用您的装饰器作为一个普通的混和函数,并让Person扩展该函数的返回值。你最终会有两个类的定义。一个是传递给decorator的,另一个是你的新类扩展的。“内部”类(传递给decorator())仍然不知道添加的道具,但是“外部”类知道:

代码语言:javascript
运行
复制
class Person extends decorator(class {
  innerProp: string = "inner";
  noKnowledgeOfMyProp: this['myProp'] = "oops"; // error
}) {
  outerProp: string = "outer"
  hasKnowledgeOrMyProp: this['myProp'] = "okay"; // okay
}

declare const p: Person;
p.myProp; // okay

这有用吗?祝好运!

票数 6
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/54892401

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档