boolean
number
string
nubmer[]
[string, nubmer]
any
void
object
인터페이스의 모든 프로퍼티가 필요하지 않을 수 있다.
선택적 프로퍼티를 가지는 인터페이스는 프로퍼티 이름 끝에 ?
를 붙여 표시한다.
interface SquareConfig {
color?: string;
width?: number;
}
프로퍼티 중 어떤것은 객체가 생성될 때만 수정가능해야할 수 있다.
프로퍼티 이름 앞에 readonly
를 넣어서 읽기 전용으로 지정할 수 있다.
interface Point {
readonly x: number;
readonly y: number;
}
interface SquareConfig {
color?: string;
width?: number;
}
//createSquare라는 함수가 SquareConfig 타입 객체를 인자로 받는 다고 가정할 때
let mySquare = createSquare({ colour: "red", width: 100 });
타입스크립트에서 객체리터럴은 다른 변수에 할당할 때나 인수로 전달할 때, 초과 프로퍼티 검사를 받는다.
이 검사에서 만약 객체리터럴이 위 예제처럼 대상 타입이 가지고 있지 않은 프로퍼티를 가지고 있으면 에러가 발생한다.
초과 프로터피 검사를 피하는 방법은 세가지이다.
let mySquare = createSquare({ width: 100, opacity: 0.5 } as SquareConfig);
[propName: string]: any;
를 추가한다.let squareOptions = { colour: "red", width: 100 };
let mySquare = createSquare(squareOptions);
클래스가 충족시켜야 하는 규약을 인터페이스로 정의할 수 있다.
클래스는 static타입과 instance타입을 가진다. 규약에 의한 검사는 인스턴스만 이루어지며 스태틱은 검사에 포함되지 않는다. 생성자가 검사에 포함되지 않는 이유가 생성자 역시 스태틱이기 때문이다.
extends
를 사용해서 인터페이스의 재사용이 가능하다.
인터페이스를 재사용성이 높은 컴포넌트로 쪼갤 때, 유연함을 제공해준다.
interface Square extends Shape, PenStroke {
sideLength: number;
}
이렇게 하나의 인터페이스는 여러개의 인터페이스를 확장할 수도 있다.
인터페이스가 클래스를 확장하면 클래스의 멤버는 상속받지만 구현은 상속받지 않는다.
말이 어려우니 예제로 보는것이 이해에 더 도움이 된다.
class Control {
private state: any;
}
interface SelectableControl extends Control {
select(): void;
}
// Error: Property 'state' is missing in type 'Image'.
class Image implements SelectableControl {
private state: any;
select() { }
}
인터페이스는 클래스를 상속했다.
클래스의 멤버를 구현하기 위해서는 그 클래스나 하위클래스로만 구현이 가능하다.
Image
는 Control
의 하위클래스가 아니므로 state
를 구현할 수 없는 것이다.
선택적 매개변수를 원한다면 매개변수 이름 끝에 ? 를 붙임으로써 해결할 수 있다.
function buildName(firstName: string, lastName?: string) {
if (lastName)
return firstName + " " + lastName;
else
return firstName;
}
메개변수에 = 값
을 통해서 전달되지 않은 인수의 기본값을 지정해 줄 수 있다.
보통은 이러한 매개변수는 순서상 뒤쪽에 위치하는 데 만약 앞쪽에 위치하고 있을 경우에는 함수 사용시 인자를 어떻게 전달할 수 있을 까
function buildName(firstName = "Will", lastName: string) {
return firstName + " " + lastName;
}
let result4 = buildName(undefined, "Adams"); // 성공, "Will Adams" 반환
이렇게 사용자가 명시적으로 undefined
를 전달해 줌으로써 초기화 매개변수를 볼 수 있다.
언젠가는 다수의 매개변수를 그룹지어 작업하기를 원하거나, 함수가 최종적으로 얼마나 많은 매개변수를 취할 지 모를 수 있다.
function buildName(firstName: string, ...restOfName: string[]) {
return firstName + " " + restOfName.join(" ");
}
let employeeName = buildName("Joseph", "Samuel", "Lucas", "MacKinzie");
...
을 통한 나머지매개변수를 이용하면 선택적 매개변수의 수를 무한으로 취급한다.
this
는 함수가 호출될 때 정해지는 변수이다.
let deck = {
suits: ["hearts", "spades", "clubs", "diamonds"],
cards: Array(52),
createCardPicker: function() {
return function() {
let pickedCard = Math.floor(Math.random() * 52);
let pickedSuit = Math.floor(pickedCard / 13);
return {suit: this.suits[pickedSuit], card: pickedCard % 13};
}
}
}
let cardPicker = deck.createCardPicker();
let pickedCard = cardPicker();
cardPicker에 의한 return
문의 this
는 deck
이 아닌 undefined
가 된다.
왜냐하면 함수 자체적인 호출이므로 발생된 객체가 없기 때문이다.
이 문제를 해결하기 위해서 화살표함수를 사용하여 알맞은 바인딩을 해줄 수 있다.
let deck = {
suits: ["hearts", "spades", "clubs", "diamonds"],
cards: Array(52),
createCardPicker: function() {
return () => {
let pickedCard = Math.floor(Math.random() * 52);
let pickedSuit = Math.floor(pickedCard / 13);
return {suit: this.suits[pickedSuit], card: pickedCard % 13};
}
}
}
화살표함수는 함수가 호출된 곳이 아닌 함수가 생성된 쪽의 this
를 캡쳐한다.
위 예제의 this.suits[pickedSuit]
의 타입은 any가 되어 경고가 표시될 수 있다.
가짜 this를 만들어서 매개변수에 전달하여 이 문제를 해결할 수 있다.
interface Card {
suit: string;
card: number;
}
interface Deck {
suits: string[];
cards: number[];
createCardPicker(this: Deck): () => Card;
}
let deck: Deck = {
suits: ["hearts", "spades", "clubs", "diamonds"],
cards: Array(52),
createCardPicker: function(this: Deck) {
return () => {
let pickedCard = Math.floor(Math.random() * 52);
let pickedSuit = Math.floor(pickedCard / 13);
return {suit: this.suits[pickedSuit], card: pickedCard % 13};
}
}
}
타입스크립트에게 createCardPicker
가 Deck
객체에서 호출된다는 것을 알려주면, this
는 Deck
타입이 되며 any
타입에 의한 오류는 발생하지 않게된다.