typescript:自动为构造函数的所有命名参数创建 getter

标签 typescript decorator typescript-generics typescript-decorator

为了使构造函数调用更具可读性,我通常更喜欢使用命名参数,如下所示:

class MyClass {
  constructor(private args: {a: number, b: string, c: boolean}) {}
}

// Example constructor call:
const x = new MyClass({a: 1, b: "hello", c: true})

但是,我还希望 abc 是公开可读的,即我希望能够调用x.ax.bx.c 而不是使用 x.args.ax.args.b x.args.c。我可以想出几种不同的方法来做到这一点(见下文),但它们都涉及重复的样板文件来显式创建属性或 getter。

有没有一种方法可以自动创建这些 setter/getter ,例如通过编写装饰器还是使用泛型?

方法 1:显式声明属性并在构造函数中填充它们

这太冗长了!

class MyClass1 {
  a: number;
  b: string;
  c: boolean;
  
  constructor(private args: {a: number, b: string, c: boolean}) { 
    this.a = args.a;
    this.b = args.b; 
    this.c = args.c;
  }
}

方法 2:存储参数并编写 getter

比方法 1 更简洁,但我希望自动创建这些 getter。

class MyClass2 {
  
  constructor(private args: {a: number, b: string, c: boolean}) {};

  get a(): number {return this.args.a}
  get b(): string {return this.args.b}
  get c(): boolean {return this.args.c}
}

最佳答案

这可以使用装饰器完成您想要的事情:

// Decorator setup

interface IndexedObject { [name: string]: any }
type Constructor = new(...args: any[]) => IndexedObject

function namedConstructorArgs <T extends Constructor> (targetConstructor: T): T {
  return class proxyConstructor extends targetConstructor {
    constructor(...args: any[]){
      super(args)
      Object.entries(args[0]).forEach(
        eachNamedArg => this[ eachNamedArg[0] ] = eachNamedArg[1]
      )
    }
  }
}

// In main program

abstract class MyClassLoggerProperties {
  a: string
  b: number
}

@namedConstructorArgs
class MyClassLogger extends MyClassLoggerProperties {

  constructor(_: MyClassLoggerProperties) {
    super()
  }

  log() {
    console.log(this.a, this.b)
  }

}

new MyClassLogger( { a: "i like flake number", b: 99 } )
  .log() // logs: I like flake number, 99

注意,我必须关闭 strictPropertyInitialization 编译器标志,以便编译器接受未在其自己的构造函数中初始化的类的属性。如果您希望保留编译器标志,您还可以将属性初始化为虚拟值。

抽象类用于确保类声明中的类属性与构造函数中的类属性相同,否则编译器不会检查它们是否一致。您可以在这些地方重复属性声明并省略构造函数中的 super() 调用,但这不是类型安全的。

关于typescript:自动为构造函数的所有命名参数创建 getter,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65446045/

相关文章:

typescript - 潜在的 Typescript 编译器错误?

javascript - 根据 window.pageYOffset 更改样式组件样式

angularjs - 用 promise 装饰器包装 $http 调用

typescript - 使用类型作为具有约束的泛型的别名

javascript - 带有组件的 Typescript 复杂泛型

typescript - 从数组类型泛型参数推断记录类型

reactjs - useMemo 返回类型错误,但 tsc 不会显示错误?

javascript - MUI v5 主题与情感/mui

python - 有没有一种 pythonic 方法来支持 Python 中的 memoize 装饰器的关键字参数?

Python:返回运行给定函数n次的函数