누구든지 TypeScript에서 생성자 오버로드를 수행 했습니까? 언어 사양 (v 0.8)의 64 페이지에는 생성자 오버로드를 설명하는 문이 있지만 예제 코드는 제공되지 않았습니다.
나는 지금 정말로 기본적인 클래스 선언을 시도하고있다. 이것처럼 보입니다.
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를 사용하여 실행하면 중복 생성자 정의가 throw됩니다. 이는 명백합니다. 어떤 도움을 주셔서 감사합니다.
TypeScript를 사용하면 오버로드를 선언 할 수 있지만 하나의 구현 만 가질 수 있으며 구현시 모든 오버로드와 호환되는 서명이 있어야합니다. 귀하의 예제에서, 이것은에서와 같이 선택적 매개 변수를 사용하여 쉽게 수행 할 수 있습니다.
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 && obj.x || 0
this.y = obj && obj.y || 0
this.height = obj && obj.height || 0
this.width = obj && obj.width || 0;
}
}
또는보다 일반적인 생성자를 사용하는 두 개의 오버로드,
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();
constructor(obj: IBox);
constructor(obj?: any) {
this.x = obj && obj.x || 0
this.y = obj && obj.y || 0
this.height = obj && obj.height || 0
this.width = obj && obj.width || 0;
}
}
IBox
생성 된 JavaScript에서. 그것은 클래스를 위해 일할 수 있고 타입으로 만들었지 만, 이것 주위의 잠재적 인 혼동이 생략되었다고 가정합니다. - Drew Noakesnumber
와public x: number
. 매개 변수가 전달 된 경우 올바른 유형인지 확인하기 위해 안전성이 중요합니다. - nikk wong
TypeScript의 기본 매개 변수를 통해 구현 수준에서 오버로드가 부족하다는 점을 해결할 수도 있습니다 (예 :
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 = {x:0,y:0, height:0, width:0}) {
this.x = obj.x;
this.y = obj.y;
this.height = obj.height;
this.width = obj.width;
}
}
편집하다:12 월 5 일 '16 일 현재벤슨의 대답더 많은 융통성을 허용하는보다 정교한 솔루션이 필요합니다.
에 관해서생성자 과부하하나의 대안은 다음과 같이 추가 오버로드를 구현하는 것입니다.정적 팩토리 메소드. 필자는 호출 인수를 테스트하는 것보다 읽기 쉽고 덜 혼란 스럽다고 생각합니다. 다음은 간단한 예입니다.
class Person {
static fromData(data: PersonData) {
let { first, last, birthday, gender = 'M' } = data
return new this(
`${last}, ${first}`,
calculateAge(birthday),
gender
)
}
constructor(
public fullName: string,
public age: number,
public gender: 'M' | 'F'
) {}
}
interface PersonData {
first: string
last: string
birthday: string
gender?: 'M' | 'F'
}
let personA = new Person('Doe, John', 31, 'M')
let personB = Person.fromData({
first: 'John',
last: 'Doe',
birthday: '10-09-1986'
})
TypeScript에서 메서드 오버로드진짜가 아니야.컴파일러가 생성 한 코드가 너무 많이 필요하고 코어 팀이 코드를 너무 많이 사용하지 않도록 노력하겠습니다. 현재 메소드 오버로딩이 언어에 존재하는 주된 이유는 API에 마법 인수가있는 라이브러리에 대한 선언을 작성하는 방법을 제공하기 위해서입니다. 서로 다른 주장을 처리하기 위해 스스로 힘든 일을해야하기 때문에 분리 된 방법 대신 과부하를 사용하는 것이별로 도움이되지 않습니다.
참고 :이 내용은 TypeScript 2.1을 반영하여 2011 년 4 월 13 일에 단순화되고 업데이트되었으며 TypeScript 1.8 답변의 기록을 참조하십시오.
개체 매개 변수를 선택적으로 지정하고 개체의 각 속성을 선택적으로 설정하려는 것 같습니다. 제공된 예에서, 과부하 구문은 필요하지 않습니다. 나는 여기서 몇 가지 대답에 대해 나쁜 습관을 지적하고 싶었다. 물론, 본질적으로 글쓰기가 가능한 가장 작은 표현은 아닙니다.box = { x: 0, y: 87, width: 4, height: 0 }
그러나 이것은 설명 된대로 클래스에서 원하는 모든 코드 힌트를 제공합니다. 이 예제에서는 하나, 일부, 모두,또는매개 변수가 없으며 여전히 기본값을 얻습니다.
/** @class */
class Box {
public x?: number;
public y?: number;
public height?: number;
public width?: number;
// The class can work double-duty as the interface here since they are identical
// Alternately, reference your own interface, e.g.: `...BoxI = {} as BoxI`
constructor(obj: Box = {} as Box) {
// Define the properties of the incoming `obj` object here.
// Setting a default value with the `= 0` syntax is optional for each parameter
let {
x = 0,
y = 0,
height = 1,
width = 1
} = obj;
// If needed, make the parameters publicly accessible
// on the class ex.: 'this.var = var'.
/** Use jsdoc comments here for inline ide auto-documentation */
this.x = x;
this.y = y;
this.height = height;
this.width = width;
}
}
이것은 정의 된 객체의 모든 속성을 가질 수없는 매개 변수를 작성하는 매우 안전한 방법입니다. 이제 다음 중 하나를 안전하게 작성할 수 있습니다.
const box1 = new Box();
const box2 = new Box({});
const box3 = new Box({x:0});
const box4 = new Box({x:0, height:10});
const box5 = new Box({x:0, y:87,width:4,height:0});
// Correctly reports error in TypeScript, and in js, box6.z is undefined
const box6 = new Box({z:0});
컴파일되면 선택적 매개 변수가 선택적이라는 것을 알 수 있습니다.이 매개 변수는 널리 사용되지만 (오류가 발생하기 쉬운) 폴백 구문의 함정을 피할 수 있습니다.var = isOptional || default;
확인하여void 0
, 이는undefined
:
var Box = (function () {
function Box(obj) {
if (obj === void 0) { obj = {}; }
var _a = obj.x, x = _a === void 0 ? 0 : _a, _b = obj.y, y = _b === void 0 ? 0 : _b, _c = obj.height, height = _c === void 0 ? 1 : _c, _d = obj.width, width = _d === void 0 ? 1 : _d;
this.x = x;
this.y = y;
this.height = height;
this.width = width;
}
return Box;
}());
||
(또는) 연산자위험을 고려하십시오.||
/ 또는 다른 응답에 표시된 것처럼 기본 폴백 값을 설정할 때 연산자를 사용합니다. 아래의 코드는 기본값을 설정하는 잘못된 방법을 보여줍니다. 평가할 때 예상치 못한 결과가 발생할 수 있습니다.허위값은 0, '', null, undefined, false, NaN :
var myDesiredValue = 0;
var result = myDesiredValue || 2;
// This test will correctly report a problem with this setup.
console.assert(myDesiredValue === result && result === 0, 'Result should equal myDesiredValue. ' + myDesiredValue + ' does not equal ' + result);
내 테스트에서는 es6 / typescript destructured object를 사용했다.Object.assign보다 거의 90 % 빠를 수 있습니다.. destructured 매개 변수를 사용하면 객체에 지정한 메서드 및 속성 만 사용할 수 있습니다. 예를 들어 다음 방법을 고려하십시오.
class BoxTest {
public x?: number = 1;
constructor(obj: BoxTest = {} as BoxTest) {
Object.assign(this, obj);
}
}
다른 사용자가 TypeScript를 사용하지 않고 속하지 않은 매개 변수를 배치하려고 시도하면z
재산
var box = new BoxTest({x: 0, y: 87, width: 4, height: 0, z: 7});
// This test will correctly report an error with this setup. `z` was defined even though `z` is not an allowed property of obj.
console.assert(typeof box.z === 'undefined')
{}
상자로 검증하지 않으면 Box로 형변환합니다. 이 방법으로 캐스팅하면 매개 변수가 정의되지 않은 새 Box를 만들 수 있습니다. IDE에서 예제를 입력 할 수 있습니다.const box1 = new Box();
캐스팅이 사용 시나리오에서 볼 수있는 오류 메시지 중 일부를 해결하는 방법을 확인할 수 있습니다. - Bensonbox.z
~이다.사실로7
귀하의 코드에undefined
. - Steven Liekensinterface BoxConfig { x?: number ...}
그 다음 줄을 바꾼다.constructor(obj: BoxConfig = {} as BoxConfig) {
- Benson
나는 이것이 오래된 질문이라는 것을 알고 있지만 1.4에서 새로운 것은 노동 조합 유형이다. 모든 함수 오버로드 (생성자 포함)에이 값을 사용하십시오. 예:
class foo {
private _name: any;
constructor(name: string | number) {
this._name = name;
}
}
var f1 = new foo("bar");
var f2 = new foo(1);
name
필드도 유형이어야합니다.string | number
대신에any
? - Carcigenicate.toString()
과.valueOf()
, Intellisense에서, 나를 위해,any
괜찮습니다. 그러나 각자 자신에게. - Joe
업데이트 (2017 년 6 월 8 일) :guyarad와 snolflake는 나의 대답에 그들의 코멘트에있는 유효한 점을 아래에 만든다. 나는 독자들이 그 답을 볼 것을 권할 것이다.벤슨,조과스노 클레이크누가 내보다 더 좋은 대답을했는지. em>
원문 답변 (2014 년 1 월 27 일)
생성자 오버로딩을 수행하는 방법의 또 다른 예는 다음과 같습니다.
class DateHour {
private date: Date;
private relativeHour: number;
constructor(year: number, month: number, day: number, relativeHour: number);
constructor(date: Date, relativeHour: number);
constructor(dateOrYear: any, monthOrRelativeHour: number, day?: number, relativeHour?: number) {
if (typeof dateOrYear === "number") {
this.date = new Date(dateOrYear, monthOrRelativeHour, day);
this.relativeHour = relativeHour;
} else {
var date = <Date> dateOrYear;
this.date = new Date(date.getFullYear(), date.getMonth(), date.getDate());
this.relativeHour = monthOrRelativeHour;
}
}
}
출처:http://mimosite.com/blog/post/2013/04/08/Overloading-in-TypeScript
선택적이고 형식화 된 매개 변수가 충분할 경우 속성을 반복하거나 인터페이스를 정의하지 않고 동일하게 수행하는 다음 코드를 고려하십시오.
export class Track {
public title: string;
public artist: string;
public lyrics: string;
constructor(track?: Track) {
Object.assign(this, track);
}
}
이 속성은 전달 된 모든 속성을 지정합니다.track
, 정의되지 않은 경우 이브Track
.
@ ShinNoNoir의 코드와 같은 다른 버전은 기본값과 스프레드 구문을 사용합니다.
class Box {
public x: number;
public y: number;
public height: number;
public width: number;
constructor({x, y, height, width}: IBox = { x: 0, y: 0, height: 0, width: 0 }) {
this.x = x;
this.y = y;
this.height = height;
this.width = width;
}
}
{}
대신에IBox
? 이미 속성 제약 조건을 열거하고 있습니다 ... - Roy Tinker
다음과 같이 처리 할 수 있습니다.
import { assign } from 'lodash'; // if you don't have lodash use Object.assign
class Box {
x: number;
y: number;
height: number;
width: number;
constructor(obj: Partial<Box> = {}) {
assign(this, obj);
}
}
Partial은 필드 (x, y, height, width) 옵션을 만들어 여러 생성자를 허용합니다.
예 : 할 수 있습니다.new Box({x,y})
높이와 너비가 없다.
그만큼= {}
정의되지 않은 값, null 값 등과 같은 거짓 값을 처리 할 수 있습니다.new Box()
너는 그걸 명심해야 해.
contructor()
constructor(a:any, b:any, c:any)
그것은new()
또는new("a","b","c")
그러므로
constructor(a?:any, b?:any, c?:any)
위와 동일하고보다 유연합니다 ...
new()
또는new("a")
또는new("a","b")
또는new("a","b","c")