Перегрузка конструктора в TypeScript
Кому-нибудь удавалось реализовать перегрузку конструкторов в TypeScript? На странице 64 спецификации языка (версия 0.8) есть упоминания о перегрузке конструкторов, но примеры кода не представлены.
В данный момент я пытаюсь создать очень простой класс, который выглядит следующим образом:
interface IBox {
x : number;
y : number;
height : number;
width : number;
}
class Box {
public x: number;
public y: number;
public height: number;
public width: number;
constructor(obj: IBox) {
this.x = obj.x;
this.y = obj.y;
this.height = obj.height;
this.width = obj.width;
}
constructor() {
this.x = 0;
this.y = 0;
this.width = 0;
this.height = 0;
}
}
При запуске с помощью команды tsc BoxSample.ts возникает ошибка о дублировании определения конструктора, что вполне понятно. Буду признателен за любую помощь.
5 ответ(ов)
Я знаю, что это старый вопрос, но в версии 1.4 добавлены объединенные типы; используйте их для всех перегрузок функций (включая конструкторы). Пример:
class Foo {
private _name: string | number;
constructor(name: string | number) {
this._name = name;
}
}
const f1 = new Foo("bar");
const f2 = new Foo(1);
Таким образом, вы можете использовать объединенные типы для создания более универсальных конструкторов и функций, что делает код более гибким и понятным.
На самом деле, может быть, уже поздно для этого ответа, но вы теперь можете сделать так:
class Box {
public x: number;
public y: number;
public height: number;
public width: number;
constructor();
constructor(obj: IBox);
constructor(obj?: IBox) {
this.x = !obj ? 0 : obj.x;
this.y = !obj ? 0 : obj.y;
this.height = !obj ? 0 : obj.height;
this.width = !obj ? 0 : obj.width;
}
}
Таким образом, вместо статических методов вы можете использовать приведённый выше подход. Надеюсь, это поможет вам!
Вы можете решить эту задачу, используя следующий код:
class Box {
x: number;
y: number;
height: number;
width: number;
constructor(obj?: Partial<Box>) {
Object.assign(this, obj);
}
}
Использование Partial
делает ваши поля (x, y, height, width) опциональными, что позволяет вам создавать экземпляры класса с различными комбинациями свойств.
Например, вы можете создать объект Box
, передав только x
и y
, не указывая height
и width
, следующим образом: new Box({ x, y })
.
Ваш класс Box
пытается определить несколько реализаций конструктора. Однако, фактически используется только последняя перегрузка сигнатуры конструктора в качестве реализации конструктора.
В приведенном ниже примере обратите внимание, что реализация конструктора определена таким образом, что она не противоречит ни одной из предыдущих перегрузок сигнатур.
interface IBox {
x: number;
y: number;
width: number;
height: number;
}
class Box {
public x: number;
public y: number;
public width: number;
public height: number;
constructor() /* Перегрузка сигнатуры */
constructor(obj: IBox) /* Перегрузка сигнатуры */
constructor(obj?: IBox) /* Реализация конструктора */ {
if (obj) {
this.x = obj.x;
this.y = obj.y;
this.width = obj.width;
this.height = obj.height;
} else {
this.x = 0;
this.y = 0;
this.width = 0;
this.height = 0;
}
}
get frame(): string {
console.log(this.x, this.y, this.width, this.height);
}
}
new Box().frame; // 0 0 0 0
new Box({ x: 10, y: 10, width: 70, height: 120 }).frame; // 10 10 70 120
// Также можно написать класс Box следующим образом:
class Box {
public x: number = 0;
public y: number = 0;
public width: number = 0;
public height: number = 0;
constructor() /* Перегрузка сигнатуры */
constructor(obj: IBox) /* Перегрузка сигнатуры */
constructor(obj?: IBox) /* Реализация конструктора */ {
if (obj) {
this.x = obj.x;
this.y = obj.y;
this.width = obj.width;
this.height = obj.height;
}
}
get frame(): string { ... }
}
Таким образом, следует помнить, что при использовании перегруженных конструкторов в TypeScript необходимо корректно реализовать последний конструктор, чтобы он соответствовал всем сигнатурам, определенным ранее.
В случае, когда необязательный параметр с определенным типом является достаточным, рассмотрите следующий код, который выполняет ту же задачу, не повторяя свойства и не определяя интерфейс:
export class Track {
public title: string;
public artist: string;
public lyrics: string;
constructor(track?: Track) {
Object.assign(this, track);
}
}
Имейте в виду, что этот код присвоит все свойства, переданные в track
, даже если они не определены в классе Track
. Это может привести к ситуации, когда объект Track
будет содержать лишние свойства, которые не предусмотрены в классе. Если это допустимо для вашего случая использования, то такая реализация может быть оправдана, но если вам важно гарантировать, что в объекте будут только свойства, определенные в классе, вам следует использовать более строгий подход к присвоению свойств.
Как вызвать один конструктор из другого в Java?
Имеют ли круглые скобки после имени типа значение при использовании new?
Как конвертировать строку в enum в TypeScript?
'unknown' против 'any': в чем разница?
Не удается использовать JSX, если не указан флаг '--jsx'