자바스크립트의 OR 연산자(||
)와 같이 A이거나 B이다 라는 의미의 타입입니다.
function logText(text: string | number) {
// ...
}
위 함수의 파라미터 text
에는 문자열 타입이나 숫자 타입이 모두 올 수 있습니다. 이처럼 |
연산자를 이용하여 타입을 여러 개 연결하는 방식을 유니온 타입 정의 방식이라고 부릅니다.
// any를 사용하는 경우
function getAge(age: any) {
age.toFixe(); // 에러 발생, age의 타입이 any로 추론되기 때문에 숫자 관련된 API를 작성할 때 코드가 자동 완성되지 않는다.
return age;
}
// 유니온 타입을 사용하는 경우
function getAge(age: number | string) {
if (typeof age === 'number') {
age.toFixed(); // 정상 동작, age의 타입이 `number`로 추론되기 때문에 숫자 관련된 API를 쉽게 자동완성 할 수 있다.
return age;
}
if (typeof age === 'string') {
return age;
}
return new TypeError('age must be number or string');
}
any
를 사용하는 경우 마치 자바스크립트로 작성하는 것처럼 동작을 하고 유니온 타입을 사용하면 타입스크립트의 이점을 살리면서 코딩할 수 있습니다.
인터섹션 타입(Intersection Type)은 여러 타입을 모두 만족하는 하나의 타입을 의미합니다.
interface Person {
name: string;
age: number;
}
interface Developer {
name: string;
skill: number;
}
type Peolpe = Person & Developer;
위 코드는 Person
인터페이스의 타입 정의와 Developer
인터페이스의 타입 정의를 &
연산자를 이용하여 합친 후 Peolpe
이라는 타입에 할당한 코드입니다.
논리적으로 유니온 타입은 OR, 인터섹션은 AND라고 생각할수 있지만, 인터페이스와 같은 타입을 다룰 때는 이와 같은 논리적 사고를 주의해야 합니다.
interface Person {
name: string;
age: number;
}
interface Developer {
name: string;
skill: string;
}
function introduce(someone: Person | Developer) {
someone.name; // O 정상 동작
someone.age; // X 타입 오류
someone.skill; // X 타입 오류
}
introduce()
함수의 파라미터 타입을 Person, Developer
인터페이스의 유니온 타입으로 정의했고
유니온 타입은 A도 될 수 있고 B도 될 수 있는 타입이지라고 생각하면 파라미터의 타입이 Person도 되고 Developer도 될테니까 함수 안에서 당연히 이 인터페이스들이 제공하는 속성들인 age나 skill를 사용할 수 있겠지라고 생각할 수 있습니다.
하지만, 타입스크립트 관점에서는 introduce()
함수를 호출하는 시점에 Person
타입이 올지 Developer
타입이 올지 알 수가 없기 때문에 어느 타입이 들어오든 간에 오류가 안 나는 방향으로 타입을 추론하게 됩니다.
const ts: Person = { name: 'ts', age: 100 };
introduce(ts); // 만약 `introduce` 함수 안에서 `someone.skill` 속성을 접근하고 있으면 함수에서 오류 발생
const js: Developer = { name: 'js', skill: 'iron making' };
introduce(js); // 만약 `introduce` 함수 안에서 `someone.age` 속성을 접근하고 있으면 함수에서 오류 발생
결과적으로 introduce()
함수 안에서는 별도의 타입 가드(Type Guard)를 이용하여 타입의 범위를 좁히지 않는 이상 기본적으로는 Person과 Developer
두 타입에 공통적으로 들어있는 속성인 name
만 접근할 수 있게 됩니다.
function introduce(someone: Person | Developer) {
console.log(someone.name); // O 정상 동작
}