如何将可选参数添加到打字稿一个装饰?

问题描述 投票:1回答:2

我想创建一个现场装饰任选可以带参数。参数应该包含以下任何值:没有什么,一个布尔或函数。我知道如何做到这一点,但我不是100%满意的结果:

export class TestClass{

   @Required(isRequired) 
   public testField: string;

}

export function isRequired():boolean{
   ... some validation logic, maybe depending on other fields...
   return result;
}

@Required的执行情况:

export function Required(expression?: boolean|Function): Function {
    return (target: any, key: string) => {
        if (expression === null || typeof expression == 'undefined') {
            expression = true;
        }
        console.log("Required found: " + expression, ":", target, key);
        ... register the field and its validation expression for later usage
    }
}

所以这个工作得很好,但是当我不想添加表达式(因此使用默认的“真”表达)我希望能够把它写这样的:

class TestClass{

   @Required
   public testField: string;

}

我得到一个错误的打字稿(TS1240)说:

当无法称为一个表达式来解决财产装饰的签名。提供的参数不匹配,通话对象的任何签名

所以,我需要写@Required()

class TestClass{

   @Required()
   public testField: string;

}

是否可以写一个装饰的实现,采用可选的参数,如果没有指定这样的说法是没有必要添加“()”?

typescript decorator typescript1.8
2个回答
3
投票

其实,这是可能的。

这是一个工作示例:

export type Target = {
  new (...args: any[]): any,
  name: string
};

export function Component(target: Target): void;
export function Component(name: string): (target: Target) => void;
export function Component(nameOrTarget: string | Target) {
  if (typeof nameOrTarget !== 'string') {
    console.log(nameOrTarget.name, ' is now decorated');
  } else {
    return function (target: Target) {
      const name = nameOrTarget || target.name;
      console.log(name, ' is now decorated');
    };
  }
}

@Component
export class MyDatabase { }

@Component('Hello Db')
export class MyHelloDatabase { }

最重要的部分是以下两行:

export function Component(target: Target): void;
export function Component(name: string): (target: Target) => void;

如果有人正在寻找更多的信息,看看这个GitHub issue


2
投票

不,你可能无法做到这一点。 其原因是,装饰有特定的签名(其取决于该装饰的类型)。 如果您使用的装饰功能,那么你不需要括号,但如果使用a decorator factory(就像你在你的例子做),那么你必须用括号调用它。

你可以做的是分离两成两个不同的功能:

function Required(target: any, key: string, expression?: boolean | Function) {
    if (expression === null || typeof expression == 'undefined') {
        expression = true;
    }
    console.log("Required found: " + expression, ":", target, key);
}

function RequiredWith(expression: boolean | Function): Function {
    return (target: any, key: string) => {
        return Required(target, key, expression);
    }
}

然后,您可以:

class TestClass {
    @Required
    public testField: string;
}

要么:

class TestClass2 {
    @RequiredWith(true)
    public testField: string;
}

(Qazxswpoi)

© www.soinside.com 2019 - 2024. All rights reserved.