들어가기에 앞서 용어 정리
구조적 타이핑
Structural Type System
타입 A 와 B가 있다고 가정하고 A 와 B를 비교할 때 A와 B가 서로 관련이 없는 독립적 타입이더라도 타입 내부의 구조에 같은 부분이 있다면 같은 타입으로 보는 타입 시스템
타입스크립트가 구조적 타입 시스템을 사용한다.
명시적 타이핑
Nominal Type System
타입 A와 B가 있다고 가정하고 A 와 B를 비교할 때 A와 B가 서로 상속관계인 경우에 같은 타입으로 보는 타입 시스템이며 관련이 없는 독립적 타입들은 그냥 말그대로 다른 타입으로 인식하는 타입 시스템.JAVA가 명시적 타입 시스템을 사용한다.
코드로 구조적 타이핑, 명시적 타이핑 알아보기
type Person = {
name: string;
}
type AgedPerson = {
name: string;
}
Person
과 AgedPerson
타입은 서로 상속관계가 아닌 독립적인 타입들이다.
명시적 타입 시스템을 사용하는 언어의 경우 두 타입은 독립적이므로 서로 다른 타입으로 인식된다.
구조적 타입 시스템을 사용하는 언어의 경우 두 타입이 독립적이더라도 내부 구조인 프로퍼티가 같은 게 있으므로 같은 타입으로 인식된다.
type Person = {
name: string;
}
type AgedPerson = {
name: string;
}
// `name` 프로퍼티를 가지고 있는 객체 리터럴을 `Person` 타입의 변수에 할당.
const person: Person = { name: 'kim' };
위 코드는 정상적으로 작동한다. 하지만 아래의 코드를 보면 헷갈릴 수 있다.
type Person = {
name: string;
}
type AgedPerson = {
name: string;
}
const aged = { name: 'kim', age: 100 };
const person: Person = aged; // Person 타입은 age 프로퍼티가 없음에도 할당 가능
aged
변수에 값으로 할당된 객체의 프로퍼티중 age
가 있음에도 불구하고 자동 코드 완성 목록에는 name
프로퍼티만 나타나는 것을 알 수 있다.
타입은 해당 타입에 들어맞는 값들의 집합으로 볼 수 있는데 Person
타입의 집합은 name
프로퍼티를 가지고 있는 모든 값 즉 조건을 충족하는 모든 객체들의 집합이다.
그렇기에 aged
변수에 할당된 객체가 age
프로퍼티를 가지고 있더라도 name
프로퍼티를 갖고 있는 객체가 되므로 Person
타입의 집합에 속한다.
type Person = {
name: string
}
type AgedPerson = {
name: string;
age: number;
}
const person: Person = {
name: 'kim',
age: 100
};
이제 위 코드를 보면 Person
집합에 age
프로퍼티가 있기 때문에 코드가 정상적으로 작동한다고 생각할 수 있다. 하지만 에러가 발생한다.
Type '{ name: string; age: number; }' is not assignable to type 'Person'.
Object literal may only specify known properties, and 'age' does not exist in type 'Person'.(2322)
타입스크립트에서 객체를 변수에 할당 시에는 특수 케이스 취급
을 받는다고 공식 문서에 나와있다.
이 특수 케이스
취급 을 받게 되는 경우는 초과 프로퍼티 체크
가 발생하며
아래의 2가지 상황일 때 초과 프로퍼티 체크가 발생된다.
위 초과 프로퍼티 체크
기능은 개발자가 초기에 타입이 명시된 변수에 값을 할당할때 잘못된 값을 할당하는 것을 방지해준다.
객체 리터럴 초과 프로퍼티 체크 관련 공식문서 링크
https://www.typescriptlang.org/docs/handbook/interfaces.html#excess-property-checks