Объединение сокращений свойств параметров с Destructuring в TypeScript
В TypeScript, когда мы хотим автоматически создавать свойства в нашем классе из определения конструктора, мы можем воспользоваться сокращением параметров параметров, например:
class Person {
constructor(public firstName : string, public lastName : number, public age : number) {
}
}
И тогда перекошенный Javascript будет:
var Person = (function () {
function Person(firstName, lastName, age) {
this.firstName = firstName;
this.lastName = lastName;
this.age = age;
}
return Person;
})();
Но если мы хотим получить объект в нашем конструкторе, это будет примерно так:
interface IPerson {
firstName : string,
lastName : string,
age: number
}
class Person {
constructor(person : IPerson) {
this.firstName = person.firstName;
this.lastName = person.lastName;
this.age = person.age;
}
}
Так как TypeScript 1.5, мы можем воспользоваться деструктурированием, например:
class Person {
constructor({firstName, lastName, age} : {firstName: string, lastName: string, age: number}) {
this.firstName = firstName;
this.lastName = lastName;
this.age = age;
}
}
Вопрос. Как скомбинировать стенографию параметров и Destructuring в TypeScript?
Я попытался определить public
перед определением объекта, например:
class Person {
constructor(public {firstName, lastName, age} : {firstName: string, lastName: string, age: number}) {
}
}
Пробовал определять его перед каждой переменной, например:
class Person {
constructor({public firstName, public lastName, public age} : {firstName: string, lastName: string, age: number}) {
}
}
Но я не имел успеха. Любые мысли?
Ответы
Ответ 1
В настоящее время нет способа сделать это коротко, поэтому самым близким вы можете объявить свойства longhand и назначить переменные из назначения деструктурирования:
class Person {
firstName: string;
lastName: string;
age: number;
constructor({firstName, lastName, age} : {firstName: string, lastName: string, age: number}) {
this.firstName = firstName;
this.lastName = lastName;
this.age = age;
}
}
Если вы это делаете... вы, вероятно, просто решите принять IPerson
и назначьте его члены без использования деструктурирования в конструкторе вообще.
Ответ 2
Другая стратегия - использовать возможность назначать переменной другого имени. Это сокращает одно повторение в конструкторе.
class Person {
firstName: string;
lastName: string;
age: number;
constructor(args: { firstName: string, lastName: string, age: number, }) {
({
firstName: this.firstName,
lastName: this.lastName,
age: this.age,
} = args);
}
}
Вы также можете перенести одно из определений в конструкторе на интерфейс.
interface PersonConstructorArgs {
firstName: string;
lastName: string;
age: number;
}
class Person {
firstName: string;
lastName: string;
age: number;
constructor(args: PersonConstructorArgs) {
({
firstName: this.firstName,
lastName: this.lastName,
age: this.age,
} = args);
}
}
Это будет полезно, если у вас есть иерархия.
interface PersonConstructorArgs {
firstName: string;
lastName: string;
age: number;
}
class Person {
firstName: string;
lastName: string;
age: number;
constructor(args: PersonConstructorArgs) {
({
firstName: this.firstName,
lastName: this.lastName,
age: this.age,
} = args);
}
}
interface EmployeeConstructorArgs extends PersonConstructorArgs {
manager: Person;
}
class Employee extends Person {
manager: Person;
constructor(args: EmployeeConstructorArgs) {
super(args);
({
manager: this.manager,
} = args);
}
}
Ответ 3
Если у вас есть доступ к Object.assign
, это работает:
class PersonData {
firstName: string
constructor(args : PersonData) {
Object.assign(this, args)
}
}
class Person extends PersonData{}
Но обратите внимание, что новые экземпляры будут заполнены чем-либо в args - вы не можете разделить только те ключи, которые хотите использовать.