Typescript:如何在实例成员属性(mixin)中使用方法装饰器?

Posted

技术标签:

【中文标题】Typescript:如何在实例成员属性(mixin)中使用方法装饰器?【英文标题】:Typescript: how to use a method decorator in an instance member property (mixin)? 【发布时间】:2021-06-16 10:03:09 【问题描述】:

背景

我们已经实现了这样的混合(简化):

export type Constructor<I> = new (...args: any[]) => I;

export interface IBaseService<T = any> 
  create: (data: any) => Promise<T>;


export function BaseService<T>(entity: Constructor<T>): Type<IBaseService<T>> 
  class BaseServiceHost implements IBaseService<T> 
    public repository: Repository<T>;

    create(data: DeepPartial<T>): Promise<T> 
      const newResource = this.repository.create(data);
      return this.repository.save(newResource);
    

  
  return BaseServiceHost;


现在我的服务扩展 BaseService 如下:

@Injectable()
export class ResponseService extends BaseService(ResponseEntity) 
  private readonly respondentService: RespondentService;
  private readonly surveyService: SurveyService;

  create = async (data: ResponseInput): Promise<ResponseEntity> => 
    const respondent = await this.respondentService.findByNaturalKey(data.respondentKey);
    const survey = await this.surveyService.findById(data.surveyId);
    return super.create( respondent, survey, ...data )
  ;

...这很好用。

PS.:create 现在必须是一个属性,否则我会收到以下错误:

Class 'IBaseTenantService<ResponseEntity>' defines instance member property 'create',
but extended class 'ResponseService' defines it as instance member function.

问题

create 方法(现在是属性),需要方法装饰器Transactional(), 但是建设

  @Transactional()  // <--- error here
  create = async (data: ResponseInput): Promise<ResponseEntity> => 
    const respondent = await this.respondentService.findByNaturalKey(data.respondentKey);
    const survey = await this.surveyService.findById(data.surveyId);
    return super.create( respondent, survey, ...data )
  ;

给出以下错误:

The return type of a property decorator function must be either 'void' or 'any'.
  Unable to resolve signature of property decorator when called as an expression.

问题

如何在create 属性中使用Transactional()?解决方法?

【问题讨论】:

@Transactional 来自typeorm-transactional-cls-hooked 还是什么? @Micael_Levi,是的。没错。 【参考方案1】:

这听起来可能很愚蠢,但你试过吗:

  @Transactional()
  async create(data: ResponseInput): Promise<ResponseEntity> 
    const respondent = await this.respondentService.findByNaturalKey(data.respondentKey);
    const survey = await this.surveyService.findById(data.surveyId);
    return super.create( respondent, survey, ...data )
  ;

?

【讨论】:

@Micael_Levi,我不能使用这个结构的原因是它引发了错误Class 'IBaseTenantService&lt;ResponseEntity&gt;' defines instance member property 'create', but extended class 'ResponseService' defines it as instance member function.

以上是关于Typescript:如何在实例成员属性(mixin)中使用方法装饰器?的主要内容,如果未能解决你的问题,请参考以下文章

Typescript知识点 --- 类

使用lambda /箭头函数的TypeScript抽象方法

获取Typescript中所有私有成员列表的方法?

如何通过指定每个属性及其值来实例化 TypeScript 中的对象?

typescript 如何通过TypeScript中的装饰器更改实例属性:http://romkevandermeulen.nl/2018/01/24/typescript-property-deco

类型“”上不存在 Typescript 错误属性“成员”