타입을 집합으로 생각하고 타입간의 좁은 타입, 넓은 타입을 파악하다
타입과 집합
타입들을 정의할 때 A타입이 B타입보다 좁을지 넓을지 생각하면 대입이 되는가 안되는가 판단할 수 있다.
string & number 는 never 타입이다. never는 집합으로 따지면 공집합이다. any는 전체집합이다.
type A = { name: string }
type B = { age: number }
type C = { name: string, age: number }
타입 A, B, C 중에 어떤 것이 가장 좁은 타입일까? 답은 C이다. C가 넓은 타입이라고 생각할 수도 있는데 이렇게 생각하면 좋다. 내가 느끼기에 타입에 충족하는 조건이 더 까다롭거나 자세하면 좁은 타입이라고 생각하면 되는 거 같다. 타입 C가 되려면 name, age를 가져야하기 때문에 더 좁은 타입이다.
좁은 타입을 넓은 타입에 넣는 건 되지만, 넓은 타입을 좁은 타입에 넣는 건 안된다.
이걸 확인할 수 있는 방법은 직접 대입해보면 된다. 하지만 넓은 타입에 더 좁은 객체 리터럴을 대입할 때 에러가 생길때가 있다.
넓은 객체 타입에 좁은 객체 타입 대입 했는데 왜 에러가
// 더 좁은 객체 리터럴을 대입했을때 에러가 생기는 경우
type A = { name: string };
type B = { age: number };
type AB = A | B;
type C = A & B;
const ab: AB = { name: 'imhwihoon' }
const c: C = { name: 'imhwihoon', age: 22, married: false} // 에러 생기는 부분
변수 c에 더 좁은 형태의 객체를 대입했을 때 오류가 생긴다.
객체 리터럴을 바로 대입하면 잉여속성 검사라고 추가적인 검사를 한다. 타입이 넓냐 좁냐 검사 뿐만 아니라 잉여속성 검사라는 걸 하기 때문에 에러가 생긴다.
그래서 잉여 속성 검사가 뭔데
타입이 명시된 변수에 객체 리터럴을 할당할 때 타입스크립트는 해당 타입의 속성이 있는지, 그 외의 속성은 없는지 확인한다. 구조적으로 봤을 땐 좁은 타입을 넓은 타입에 할당하려 했으니까 할당 가능 검사 단계에서는 에러가 발생하지 않은 것이다. 하지만 그 외의 속성이 있는지 없는지 확인하는 과정인 잉여 속성 검사에서 잉여 속성을 검사한 후 있으면 에러를 발생시킨다. 잉여 속성 검사를 하는 이유는 오타나 의도치 않은 속성을 입력했을때 등의 에러를 방지해준다.
type A = { name: string };
type B = { age: number };
type AB = A | B;
type C = A & B;
const ab: AB = { name: 'imhwihoon' }
const obj = { name: 'imhwihoon', age: 22, married: false}
const c: C = obj;
중간에 데이터를 변수로 빼주고 다시 할당하면 잉여 속성 검사를 하지 않기때문에 에러가 발생하지 않는다.
'Front-End > TypeScript 기초' 카테고리의 다른 글
[TypeScript] union(|), intersection(&) 그리고 상속 (extends) (0) | 2024.05.23 |
---|---|
[TypeScript] 커스텀 타입, enum, keyof, typeof ~ (0) | 2023.12.18 |
[TypeScript] 타입스크립트 타입 표기법 (0) | 2023.12.14 |
[TypeScript] 타입스크립트 시작하기 (0) | 2023.12.13 |