将参数传递给TypeScript中的超类的最有效方法

b09cbbtk  于 2023-08-07  发布在  TypeScript
关注(0)|答案(3)|浏览(151)

解决这个问题的最好方法是什么?我喜欢我们在构造函数中定义属性的方式,TSC为我们解决响应做了所有的魔法。代码行,以便在JavaScript中为props赋值--我在这里对department所做的。
但我很好奇,是否也有一些对继承有用的东西?有没有一种方法,让我们假设初始化一个具有所有属性的子类,并将它们沿着超级调用,而不重复这里的所有属性?
我不想为了初始化类和满足超级调用而手动将/* 基类的所有其他属性 */放在那里。
提前感谢和问候。

class Manager extends Employee {
  constructor(public department: number, /* all the other attributes of the base class*/ ){
    super( /* all the other attributes of the base class*/ );
  }
}

let myEmp = new Employee(1, "James"); // Base class
let myMng = new Manager (101, 2, "Jane" ); // Subclass

字符串

**更新:**在你的一些有用的反馈给我带来了一些关于TypeScript的其他曲目之后,我最终来到了这里。我将尝试稍微调整一下,以摆脱在超级调用中显式命名和列出超类成员的方式。听到一些关于这种方法的想法将是很好和有帮助的。

class Manager extends Employee {
  constructor(public department: number, empData: Employee) {
    super(empData.id, empData.name);
  }
}

更新#2 +答案:经过@AluanHaddad的一些有用的提示和一些深入的TSC的实用程序类型,这就是我要找的。

感谢你们所有人!

class Employee {
  constructor(public id: number, public name: string) {}
}

class Manager extends Employee {
  constructor(
    public department: number,
    ...superClassData: ConstructorParameters<typeof Employee >
  ) {
    super(...superClassData);
  }
}

let myEmp = new Employee(1, "James"); // Base class
let myMng = new Manager (101, 2, "Jane" ); // Subclass

np8igboo

np8igboo1#

你可以在这里利用 parameter object 模式。而不是通过一次传递多个参数,一个参数多个字段。

type EmployeeParams = {
    // superclass params
  }

  type ManagerParams = {
    department: number
  } & EmployeeParams;

  class Employee {
    // declare all the fields
    constructor(params: EmployeeParams){
      // assign all the fields
    }
  }

  class Manager extends Employee {
    department: number;
    constructor(params: ManagerParams){
      super(params);
      this.department = params.department;
    }
  }

字符串
请注意,现在需要在类上显式声明单独的字段。

3pvhb19x

3pvhb19x2#

不要使用构造函数的位置参数,而是使用具有命名属性的对象。因为“options”对象将是基类的options对象类型的超类型,所以你可以只传递整个对象:

interface FooArgs {
  a: number
  b: string
}

class Foo {
  public a: number;
  public b: string;

  constructor(args: FooArgs) {
    this.a = args.a;
    this.b = args.b;
  }
}

interface BarArgs extends FooArgs {
  c: number
}

class Bar extends Foo {
  public c: number;
  
  constructor(args: BarArgs) {
    super(args);
    this.c = args.c;
  }
}

字符串
Playground
这还有一个额外的好处,即在调用站点上使args更易于阅读,在调用站点上,您可以new这些对象:

const John = new Employee({ age: 32, salary: 60000, name: 'John Smith' });
const Mary = new Manager({ age: 45, salary: 90000, name: 'Mary Brown', directReports: 7 });

vsaztqbk

vsaztqbk3#

下面的两个代码示例将rest属性和类型声明用于特定于类的参数配置。
一个人可以去与...

type employeeConfig = {
  field_1: string,
  field_2: number,
}
type managerConfig = {
    department: number,
} & employeeConfig;

class Employee {
  public field_1: string;
  public field_2: number;

  constructor({ field_1, field_2 }:employeeConfig) {

    this.field_1 = field_1;
    this.field_2 = field_2;
  }
}

class Manager extends Employee {
  public department: number;

  constructor({ department, ...restConfig }:managerConfig) {
    super(restConfig);

    this.department = department;
  }
}

const manager = new Manager({ department: 12, field_2: 2, field_1: "foo" });

console.log({ manager });

字符串
。甚至和。。

type employeeConfig = {
  field_1: string,
  field_2: number,
}
type managerConfig = {
    department: number,
} & employeeConfig;

class Employee {
  constructor(config:employeeConfig) {

    Object.assign(this, config);
  }
}

class Manager extends Employee {
  constructor({ department, ...restConfig }:managerConfig) {
    super(restConfig);

    Object.assign(this, { department });
  }
}

const manager = new Manager({ department: 12, field_2: 2, field_1: "foo" });

console.log({ manager });


后者在config方面更灵活,但需要牺牲任何公共类字段的显式声明。

相关问题