<aside> 💡 자바스크립트는 객체 리터럴이나 익명 함수 등을 사용하기 때문에 명시적으로 타입을 지정하는 것보다 코드의 구조 관점에서 타입을 지정하는게 더 잘 어울릴 수도 있다.
</aside>
타입스크립트에서 다른 타입 간에 호환 여부를 점검하는 것을 타입 호환이라고 한다. 아래 Avengers
클래스는 Ironman
인터페이스를 상속받아 구현한 게 아닌데도 에러가 발생하지 않는다. 타입스크립트에선 타입에 정의되어 있는 속성의 타입을 가지고 코드가 호환되는지 확인하기 때문이다.
interface Ironman {
name: string;
}
class Avengers {
name: string;
}
let ironMan: Ironman;
ironMan = new Avengers(); // ok 타입 호환
<aside> 💡 객체 속성, 함수 파라미터 등이 비교하는 대상보다 더 많다면 구조적으로 더 크다고 볼 수 있다.
</aside>
코드 구조 관점에서 타입이 서로 호환되는지 판단하는 것을 구조적 타이핑이라고 한다. 아래 예제에서 capt
객체와 Avengers
인터페이스 모두 name
속성이 있기 때문에 capt
와 hero
타입은 서로 호환된다. 더 엄밀하게 말하면 capt
객체 타입이 구조적으로 Avengers
보다 크기 때문에 hero
에 할당(호환)될 수 있는 것.
interface Avengers {
name: string;
}
let hero: Avengers;
const capt = { name: 'Captain', location: 'Seoul' };
hero = capt; // ok 타입 호환
함수 호출 역시 마찬가지다. capt
객체에 name
속성이 있으므로 assemble
함수의 인자로 넘길 수 있다.
function assemble(param: Avengers) {
console.log(param.name);
}
assemble(capt); // 'Captain' (타입 호환)
<aside> 💡 interface / class / 객체 등에서 할당 연산자의 右项이 구조적으로 더 크다면 타입은 호환될 수 있다.
</aside>
아래 developer = person
코드에서 오른쪽에 있는 person
타입을 developer
에 할당하려고 하면 에러가 발생한다(타입 호환 불가). developer
에서 필요한 skill
속성을 person
이 가지고 있지 않기 때문이다. 즉, 구조적으로 더 작은 person
을 developer
에 할당하려고 해서 발생하는 에러다.
interface Developer {
name: string;
skill: string;
}
interface Person {
name: string;
}
let developer: Developer;
let person: Person;
developer = person; // Error! 타입 호환 불가
// TS2741: Property 'skill' is missing in type 'Person' but required in type 'Developer'.
person = developer; // ok 타입 호환
Person
인터페이스를 클래스로 바꿔도 결과는 동일하다. 타입스크립트에서 타입 호환을 검증할 때 내부에 존재하는 속성과 타입에 대해서만 비교한다. interface
type
class
등은 상관없다.