Intersection
타입은 말 그대로 여러타입이 합쳐진 하나의 타입을 말합니다.
두개의 Interface
타입의 인자를 전달받아 하나의 객체로 합쳐주는 함수를 만들어주세요.
interface User {
name: string;
}
interface Action {
do(): void;
}
function createUserAction(u: User, a: Action):{무엇이 반환?} {
return {...u, ...a};
}
이런 경우에 함수의 반환값을 무엇으로 지정해 주어야 할까요? 바로 Intersection을 사용해주면 됩니다.
User & Action
이런식으로&
기호를 이용해 두가지 타입을 합쳐줄 수 있습니다.function createUserAction(u: User, a: Action): User & Action { return {...u, ...a}; }
만들어진 함수를 사용해보면 다음과 같이 타입이 적용된 것을 확인할 수 있습니다.
이렇게 Intersection
을 사용하면 기존타입을 이용한 상속과 같은걸 사용하지 않고 간단하게 사용할 수 있습니다.
만약 인자 두개를 받아서 비교를 해주는 함수를 만들고 싶다면 어떻게 구현해야 할까요?
function compare(x: string, y: string): boolean {
if (x === y) {
return true;
} else {
return false;
}
}
이렇게 사용해줄 수 있겠죠?
하지만 인자로 문자뿐만 아니라, 숫자도 넣어주고 싶다면 다음과 같이 유니온 타입을 통해 간단히 구현할 수 있습니다.
function compare(x: string | number, y: string | number): boolean {
if (x === y) {
return true;
} else {
return false;
}
}
위와같이
|
를 이용해 두가지 모두 들어올수 있도록 만들어주는 것을 유니온타입이라고 합니다.
또한 문자와 문자 숫자와 숫자를 비교하고 싶다면typeof
를 이용해서 타입가드를 사용해주면됩니다.function compare(x: string | number, y: string | number): boolean { if (typeof x === "number" && typeof y === "number") { return x === y ? true : false; } if (typeof x === "string" && typeof y === "string") { return x.localeCompare(y) ? true : false; } }
또한 문자와 문자 / 숫자와 숫자 만 입력받게끔 해주기 위해 함수시그니처 오버로딩을 사용할 수 있습니다.
function compare(x: number, y: number): boolean;
function compare(x: string, y: string): boolean;
function compare(x: string | number, y: string | number): boolean {
if (typeof x === "number" && typeof y === "number") {
return x === y ? true : false;
}
if (typeof x === "string" && typeof y === "string") {
return x.localeCompare(y) ? true : false;
}
}
다음과 같이 문자/숫자를 혼용하면 에러가 나오는 것을 볼 수 있습니다.
위에서 작성한 User , Action인터페이스중 하나의 타입을 인자로 받는 함수를 만들어 보아요.
interface User {
name: string;
}
interface Action {
do(): void;
}
function process(v: User | Action) {}
이런 경우에 함수안에서 v
가 User
인지 Action
인지 어떻게 알 수 있을까요
함수 안에서 if문
을 통해 인터페이스 안에 있는 do
메소드가 있는지 확인해 보겠습니다.
function process(v: User | Action) {
if(v.do)
}
아래와 같이 do는 User와 Action의 공통된 타입이 아니기 때문에 에러가 나오는 것을 확인할 수 있습니다.
이런 경우에는 아래와 같이 Type Assertions (타입어설션)을 통해 타입이 Action이라고 가정해 줄 수 있습니다.
function process(v: User | Action) {
if((<Action>v).do){
(<Action>v).do
}
}
Type Assertions (타입어설션)은 개발자가 타입스크립트에게 지금 뭘 하고 있는지 말해주는 것으로 볼 수 있습니다.
하지만 매번 이렇게 타입가드를 해줄 수는 없으니 직접 개발자가 타입가드를 만들어 사용해 줄 수 있습니다.
function isAction(v: User | Action): v is Action {
return (<Action>v).do !== undefined;
}
v
를 인자로 받은후 만약 v.do
가 존재한다면 v
는 Action
이다. 라고 하는 코드입니다.
이를 적용해서 위 코드를 다시 작성해 본다면 아래와 같습니다.
function isAction(v: User | Action): v is Action {
return (<Action>v).do !== undefined;
}
function process(v: User | Action) {
if (isAction(v)) {
v.do;
} else {
v.name;
}
}
유니온 타입을 사용했을 경우에는 꼭 타입가드를 사용해서 안전한 코딩을 해요!