✏️ 각 타입의 속성들 간의 관계를 제대로 모델링하면, 타입스크립트가 코드의 정확성을 체크하는데 도움이 된다.
❓ 다만, 이 코드에서는 타입 분기 후 layer가 포함된 동일한 코드가 반복되고 있다.
✏️ 태그된 유니온은 타입스크립트 타입 체커와 잘 맞아 타입스크립트에서 잘 보인다. 이 패턴을 기억해서 적용해보자. 어떤 데이터 타입을 태그된 유니온으로 표현할 수 있다면, 그렇게 하자. 또는 여러 개의 선택적 필드가 동시에 값이 있거나 동시에 undefined인 경우도 태그된 유니온 패턴이 잘 맞는다.
🔗 선택적 필드, 동시에 값이 있거나, 동시에 undefined
interface Person {
name: string;
// These will either both be present or not be present
placeOfBirth?: string;
dateOfBirth?: Date;
}
타입 정보를 달고 있는 주석은 문제가 될 가능성이 높다. placeOfBirth와 dateOfBirth필드는 실제로 관련되어 있지만, 타입 정보에는 어떠한 관계도 표시되지 않았다.
const alanT: Person = {
name: 'Alan Turing',
birth: {
// ~~~~ Property 'date' is missing in type
// '{ place: string; }' but required in type
// '{ place: string; date: Date; }'
place: 'London'
}
}
⭐️ Person 객체를 매개변수로 받는 함수는 birth 하나만 체크하면 된다.
function eulogize(person: Person) {
console.log(person.name);
const {birth} = person;
if (birth) {
console.log(`was born on ${birth.date} in ${birth.place}.`);
}
}
타입의 구조를 손댈 수 없을 때는 (API), 앞서 다룬 인터페이스의 유니온을 사용해서 속성 사이의 관계를 모델링하자.
interface Name {
name: string;
}
interface PersonWithBirth extends Name {
placeOfBirth: string;
dateOfBirth: Date;
}
type Person = Name | PersonWithBirth;
중첩된 객체에서도 동일한 효과를 본다.
function eulogize(person: Person) {
if ('placeOfBirth' in person) {
person
// ^? (parameter) person: PersonWithBirth
const {dateOfBirth} = person; // OK
// ^? const dateOfBirth: Date
}
}
앞의 두 경우 모두 타입 정의를 통해 속성 간의 관계를 더 명확하게 만들었다.
📍 요약
유니온 타입의 속성을 여러 개 가지는 인터페이스에서는 속성 간의 관계가 분명하지 않기 때문에 실수가 자주 발생하므로 주의해야 한다.
유니온의 인터페이스보다 인터페이스의 유니온이 더 정확하고 타입스크립트가 이해하기도 좋다.
타입스크립트가 제어 흐름을 분석할 수 있도록 타입에 태그를 넣는 것을 고려해야 한다. 태그된 유니온은 타입스크립트와 매우 잘 맞기 때문에 자주 볼 수 있는 패턴이다.