유니온 (Union) 이란?
- 타입스크립트에서 타입을 병합할 수 있는 방법 중 하나임
|
기호를 이용함- 아래의 코드에서
StringOrNumberType
은string
이나number
타입 두가지를 병합한 타입임 - 타입에 유연성을 제공함
type StringOrNumberType = string | number;
let stringOrNumberType: StringOrNumberType = "김모씨";
stringOrNumberType = 100;
타입 가딩 (Type Guarding) 이용
- Union 타입을 이용하는 경우 아래와 같이
instnaceof
혹은typeof
를 통한 타입 가딩을 이용해 동작 방식을 지정해줄 수 있음
function combine(input1: number | string, input2: number | string) {
if (typeof input1 === "number" && typeof input2 === "number") {
return input1 + input2;
} else {
return input1.toString() + input2.toString();
}
}
const combinedNumbers = combine(1, 5); // returns 6
const combinedStrings = combine("Hello, ", "world!"); // returns "Hello, world!"
유니온 타입 예제
- 몇가지든 추가 가능함
type StringOrNumberOrBooleanType = string | number | boolean;
type AsyncState = "REQUEST" | "LOADING" | "DONE" | "ERROR";
let state: AsyncState = "DONE"; // 정상 작동
state = "FINISH"; // 에러 `AsyncState` 타입에 없으므로 할당할 수 없는 값
리스트의 유니온 (Union List)
- 리스트 타입도 유니온 타입을 이용하는 것이 가능함
- 단, 표기상 몇가지 헷갈리는 점을 잘 알아둬야 함
string[] | number[]
와(string | number)[]
의 차이를 잘 이해해야 한다.
string[] | number[]
이해하기
// string 으로 구성된 list 혹은 number 으로 구성된 list
type StringListOrNumberList = string[] | number[];
// 문자열로 된 리스트 혹은 number 으로 된 리스트만 가능하다.
let list1: StringListOrNumberList = ["a", "b", "c"];
// 두개를 같이 넣으면 에러 난다.
let list2: StringListOrNumberList = ["a", "b", "c", 3]; // 에러
(string | number)[]
이해하기
// 이 경우엔 string 혹은 number 원소를 가진 리스트 표현이 가능하다.
type StringOrBooleanList = (string | number)[];
let list3: StringOrBooleanList = ["a", "b", "c", 3]; // 정상
유니온을 통해 인터페이스 결합하기
- 자바스크립트에서 기본으로 지원하는 Primitive 타입 외에도 인터페이스로 정의한 것도 Union 으로 결합이 가능하다.
- 아래의 코드 예제는
Animal
과Human
인터페이스를 결합한 예시를 보여준다. - 두 인터페이스가 결합된
AnimalOrHuman
타입을 변수에 이용하면, 타입스크립트는 오브젝트 내부의 프로퍼티 값을 보고 해당 변수가Animal
타입인지Human
타입인지 유추해낸다.- 그리고 반드시 둘 중 하나의 타입으로 유추 가능해야 한다.
type Sex = "male" | "female";
interface Animal {
name: string;
sex: Sex;
}
interface Human {
name: string;
sex: Sex;
phone: string;
}
type AnimalOrHuman = Animal | Human;
let human1: AnimalOrHuman = {
name: "김똘똘",
sex: "male",
phone: "010",
};
// Human 에게만 있는 phone 속성 값이 있으므로 타입스크립트는 이를 Human 이라고 유추 가능
console.log(human1);
let animal1: AnimalOrHuman = {
name: "닭",
sex: "female",
};
// Human 에게만 있는 phone 속성 값이 없으므로 타입스크립트는 이를 Animal 이라고 유추 가능
console.log(animal1);
// 이미 Animal 타입으로 추론했기 때문에 phone 속성이 없다고 여겨져 Human 타입에만 있는 phone 속성을 불러오려 하면 에러가 남
console.log(animal1.phone);
마우스를 올려서 추론된 타입을 확인해본 모습
타입 추상화를 잘 해야 하는 이유
- 사실
interface
나type
등으로 타입 추상화를 하지 않고 그냥 오브젝트에 들어갈 것을{}
로 표현해도 되긴 한다. - 근데 그 경우에 에러 메세지를 보고 해당 타입이 왜 틀렸는지 디버깅하기 매우 어려워지므로 평소에 타입 추상화를 잘 해두는 것이 좋다.
let animalOrHuman:
| {
name: string;
sex: Sex;
}
| {
name: string;
sex: Sex;
phone: string;
} = {
name: "김똘일",
sex: "male",
};
console.log(animalOrHuman);
console.log(animalOrHuman.phone); // 에러, name 과 sex 밖에 정의하지 않았으므로 위의 타입으로 추론되었을 것이다.
실제 에러 메세지
let animalOrHuman2: Animal | Human = {
name: "김똘일",
sex: "male",
};
console.log(animalOrHuman);
console.log(animalOrHuman.phone); // 에러, 간단한 에러 메세지
'phone' does not exists on type 'Animal' 이라고 알려줌으로써 파악하기가 더 쉽다.
'Animal' 타입에 'phone' 이란 프로퍼티는 없구나 하고 인식할 수 있다.
Union 은 n 개의 OR 중 하나의 타입만 만족하면 그 이후에는 어떻게 해도 된다.
- union 은 n 개의 타입 중 하나만 만족하면 그 이후에는 어떻게 해도 된다.
- 하나의 타입만 만족 후에 다른 타입의 속성 중 하나가 있든 다 있든 없든 상관하지 않는다.
- 당연히 n 개의 타입을 다 만족해도 된다.
- 근데 하나의 타입도 만족하지 못하는 경우엔 에러가 난다.
interface Person {
name: string;
age: number;
}
type DeveloperMajor = "backend" | "frontend" | "devops";
interface Developer {
developerMajor: DeveloperMajor;
workExperience: number;
}
type PersonOrDeveloper = Person | Developer;
let jake: PersonOrDeveloper = {
name: "jake",
age: 20,
};
let jake2: PersonOrDeveloper = {
name: "jake",
age: 20,
workExperience: 5,
};
let jake3: PersonOrDeveloper = {
name: "jake",
age: 20,
workExperience: 5,
developerMajor: "backend",
};
// Person 혹은 Developer 둘 다 만족하지 못하는 경우엔 에러가 남
// 둘 중에 하나라도 만족하는 것은 에러나지 않음
// 하나를 만족한 이후에 추가적인 다른 1개의 속성을 갖는 것도 에러나지 않음
// 둘 다 만족하는 것도 에러나지 않음
// 무조건 두개의 타입 중 하나라도 만족해야 함
let jake4: PersonOrDeveloper = {
name: "jake",
workExperience: 5,
};
반응형
'Typescript' 카테고리의 다른 글
TS009. 타입스크립트의 내로잉 (Narrowing) 이란? (0) | 2023.12.28 |
---|---|
TS008. Typescript Intersection 이란? (0) | 2023.12.28 |
TS006. 타입스크립트 타입 캐스팅 및 주의점 (0) | 2023.12.27 |
TS005. 타입스크립트의 타입 추론 (type inference) (0) | 2023.12.27 |
TS004. 타입스크립트의 Enum 타입 간단하게 알아보기 (0) | 2023.12.27 |