TIL

191126_TIL(타입스크립트와 덕타이핑)

인터페이스와 클래스

인터페이스는 일반적으로 타입 체크를 위해 사용되며 변수, 함수, 클래스에 사용할 수 있다. 인터페이스에 선언된 프로퍼티 또는 메소드의 구현을 강제하여 일관성을 유지할 수 있도록 하는 것이다.

인터페이스는 프로퍼티와 메소드를 가질 수 있다는 점에서 클래스와 유사하나 직접 인스턴스를 생성할 수 없고 모든 메소드는 추상 메소드이다.

클래스 선언문의 implements 뒤에 인터페이스를 선언하면 해당 클래스는 지정된 인터페이스를 반드시 구현하여야 한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 인터페이스의 정의
interface UserInfo {
username: string;
password: string;
age: number;
}

// User 클래스는 UserInfo 인터페이스를 구현하여야 한다.
class User implements UserInfo {
constructor (
public username: string,
public password: string,
public age: number
) { }
}

const user = new User('kim', '1234', 25);

인터페이스는 프로퍼티뿐만 아니라 메소드도 포함할 수 있다. 단, 모든 메소드는 추상 메소드이어야 한다. 인터페이스를 구현하는 클래스는 인터페이스에서 정의한 프로퍼티와 추상 메소드를 반드시 구현하여야 한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// 인터페이스의 정의
interface Animal {
name: string;
crying(): void;
}


// 인터페이스를 구현하는 클래스는 인터페이스에서 정의한 프로퍼티와 추상 메소드를 반드시 구현하여야 한다.

class Dog implements Animal {
// 인터페이스에서 정의한 프로퍼티의 구현
constructor(public name: string) {}

// 인터페이스에서 정의한 추상 메소드의 구현
crying() {
console.log('bowwow');
}
}

function cryingSound(dog: Animal): void {
dog.crying();
}

const myDog = new Dog('Pomeranian');
cryingSound(myDog); // bowwow

덕 타이핑

TypeScript 의 핵심 원리 중 하나는 값이 가지는 형태 에 초점을 맞추는 타입-체킹을 한다는 것이다. 이를 “덕 타이핑(duck typing)” 또는 “구조적 하위 유형화(structural subtyping)”라고도 한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
interface Duck {
quack(): void;
}

class MallardDuck implements IDuck {
quack() {
console.log('Quack!');
}
}

class RedheadDuck {
quack() {
console.log('q~uack!');
}
}

function makeCrying(duck: Duck): void {
duck.quack();
}

makeCrying(new MallardDuck()); // Quack!
makeCrying(new RedheadDuck()); // q~uack! // 5

makeCrying함수에 인터페이스 Duck을 구현하지 않은 클래스 RedheadDuck의 인스턴스를 인자로 전달하여도 에러 없이 처리된다.

TypeScript는 해당 인터페이스에서 정의한 프로퍼티나 메소드를 가지고 있다면 그 인터페이스를 구현한 것으로 인정한다.

인터페이스를 변수에 사용할 경우에도 덕 타이핑은 적용된다.

1
2
3
4
5
6
7
8
9
10
interface LabelledValue {
label: string;
}

function printLabel(labelledObj: LabelledValue) {
console.log(labelledObj.label);
}

let myObj = { size: 10, label: "Size 10 Object" };
printLabel(myObj);

변수 myObj는 인터페이스 LabelledValue과 일치하지는 않는다. 하지만 LabelledValue의 label프로퍼티를 가지고 있으면 인터페이스에 부합하는 것으로 인정된다.

타입스크립트의 타입 체킹은 프로퍼티가 순서대로 제공될 것을 요구하지 않는다. 다만, 인터페이스에서 요구하는 프로퍼티가 있는지 확인한다.

참고

TypeScript docs

poiemaweb

Share