class NewPerson implements Person { name: string; age: number; createTime: Date; constructor(name: string, age: number) { this.name = name; this.age = age; this.createTime = new Date(); } getCreateTime() { return `该对象的创建时间是:${this.createTime}`; } }
![]() | 1 X0V0X 192 天前 这就是人们说的 java 味吗 |
![]() | 2 FrankFang128 192 天前 大部分 JSer 不用装饰器 |
3 jackge0323 192 天前 这部分可以跳过,基本不用。 |
![]() | 4 linkopeneyes 192 天前 这种情况还是继承比较好,当然类装饰器也可以规定类长什么样子,这样就可以要求强制继承一个带这个方法的类了 |
![]() | 5 lisongeee 192 天前 ![]() ts 认为装饰器不会改变类型,因此你声明的时候类型是啥它就是啥 达到你想要的效果也很简单,将声明改为调用 const Person = LogTime( class { name: string; age: number; constructor(name: string, age: number) { this.name = name; this.age = age; } }, ); |
![]() | 6 lanten 192 天前 目前再 TS 中的任何装饰器(类/方法/属性/参数装饰器)都无法更改调用该装饰器目标的原始类型. 由于你的 getCreateTime 方法是在装饰器中添加的, 且在原始类(Person)中没有该方法的签名, 所以 person 实例在类型系统中压根没有 getCreateTime 方法, 报错符合预期. 声明 `interface Person` 是不完美的, 这会破坏类型系统的准确性. (但也不是不行) 我个人认为你这种场景应该使用基类派生(extends), 而不是装饰器, 通常类装饰器需要配合方法装饰器或属性装饰器才能体现其价值 |
![]() | 7 DreamingCTW OP |
![]() | 8 DreamingCTW OP @sjhhjx0122 #4 他假设的场景是,为每一个 class 的实例对象创建时都记录一个创建时间,所以用了装饰器,这样可以很方便的为每一个 class 上写 @LogTime ,只是我在学习的过程中发现了有这个问题。 |
![]() | 9 sillydaddy 192 天前 可以给装饰器定义明确的返回类型: ``` interface WithCreateTime { getCreateTime(): string; } function LogTime<T extends Constructor>(Base: T): T & Constructor<WithCreateTime>; ``` 上面的 LogTime 函数定义中,明确指定了返回类型:T & Constructor<WithCreateTime> 。并且与 LogTime 实际返回值的类型是一致的。 |