글 작성자: 망고좋아
반응형

🎯 타입스크립트 유니온 타입 & 인터섹션 타입

interface Animal {
    eat: () => void
    sleep: () => void
}

class Dog implements Animal {
    eat() {}
    sleep() {}
}

class Cat implements Animal {
    eat() {}
    sleep() {}
}
  • Dog에만 bark라는 메서드를 추가할 때 Animal에 bark 메서드를 추가하면 interface를 구현하는 클래스는 구현의 의무가 있기 때문에 Cat까지 bark메서드를 구현해야 한다.
  • 기존 타입, 인터페이스 변경은 이미 그 타입을 사용하고 있는 코드에 똑같은 변경을 가해줘야 한다.
  • 만약 해당 타입을 쓰는 모든 코드에 변경을 가하지 않고 특정 코드만 자유롭게 타입을 확장하고 싶을 땐 어떻게 해야 할까?

Intersection → And

  • A & B : A타입이면서 B타입

Union → Or

  • A | B : A타입, B 타입 둘 중 하나

 

📝 Union Type

let one: string | number | boolean;

one = 1;
one = '1';
one = true;
  • |를 사용
  • Type A, Type B가 있을 때 A와 B를 유니온 하면 A타입 또는 B 타입 둘 중 하나
  • one: string이거나 number 둘 중 하나

 

📕 Union Type 언제 사용할까?

type A = string | number;

// An interface can only extend an object type or intersection of object types with statically known members.
interface StrOrNum extends A {
    a: string;
}

// Ok
type StrOrNum = {
    a: string;
} & (string | number);
interface Animal {
  eat: () => void;
  sleep: () => void;
}

interface Human {
  think: () => void;
}

type Developer = (Animal | Human) & {
  work: () => void;
};
  • 여러 타입 중 하나가 올 것이라고 가정할 때 사용
  • 단, 인터페이스에 유니온 타입을 사용하는 경우 인터페이스 유니온 타입을 확장하지 못함
  • 이럴 때는 type alias와 &를 사용해야 함

 

📕 Union Type는 동시에 여러 타입이 될 수 없다.

type Human = {
    think: () => void;
};

type Dog = {
    bark: () => void;
}
declare function getEliceType(): Human | Dog; // 반환 타입이 Human or Dog인 getEliceType 함수

const elice = getEliceType(); // getEliceType 함수를 호출한 결과를 elice 라는 변수에 할당

// Property 'think' does not exist on type 'Human | Dog'.
elice.think();

// Property 'bark' does not exist on type 'Human | Dog'.
elice.bark();
  • elice를 Human or Dog라는 유니온 타입으로 만들어 주어도 think, bark 둘 중 어느 것도 사용하지 못함
  • why? → elice가 런타임에서 Human인지 Dog인지 확신할 수 없기 때문에
    • elice.think() 함수를 호출할 때 elice가 Human이라면 괜찮지만 Dog라면 think를 호출할 수 없기 때문에 컴파일 단계에서 에러
    • 해결 방법 : 타입 가드 ⇒ elice가 Human 일 때 think함수를, Dog 일 때 bark함수를

 

📝 Intersection Type

type Human = {
    think: () => void;
};

type Developer = {
    word: () => void;
}

const elice: Human & Developer = {
    think() {
        console.log("생각 중");
    } ,
    word() {
        console.log("업무 중");
    } 
}
  • 기존 타입을 대체하지 않으면서 기존 타입에 새로운 필드를 추가하고 싶을 때 사용
  • 교차 타입(Intersection Type)은 &(앰퍼샌드)를 사용한다.
  • Type A, Type B가 있을 때 A와 B를 인터섹션 하면 A타입이면서 B타입이라는 의미
  • 즉, Elice는 Human이면서 Developer라서 두 개의 속성을 동시에 가질 수 있다.

 

📕 Intersection Type는 언제 사용할까?

type Human = {
    think: () => void;
};

type Developer = {
    word: () => void;
}

type Student = {
    study: () => void;
}

const elice: Human & Developer & Student = {
    think() {
        console.log("생각 중");
    } ,
    word() {
        console.log("업무 중"); 
    } ,
    study() {
        console.log("공부 중");
    } 
}
  • Intersection Type은 기존 타입을 대체하지 않으면서 기존 타입에 새로운 필드를 추가하고 싶을 때 사용 ⇒ 확장하고 싶을 때 사용
  • 기존의 Human & Developer 타입의 elice에 student 타입을 추가해 기존 타입은 변경하지 않고 확장 가능

 

📕 Intersection Type 주의할 점 : 각 타입에 겹치는 필드가 있다면 어떻게 될까?

🛠 타입이 같을 때 : Ok

type Developer = {
    output: string;
    developer: () => void;
}

type Designer = {
    output: string;
    design: () => void;
}

const 개자이너: Developer & Designer = {
    output: 'sth cool', // ok
    developer() {
        console.log("업무 중");
    },
    design() {
        console.log("업무 중");
    }
}
  • 가능

 

🛠 타입이 다를 때 : Error

type Developer = {
    output: number; // ** 
    developer: () => void;
}

type Designer = {
    output: string;
    design: () => void;
}

const 개자이너: Developer & Designer = {
    output: 'sth cool', // error
    developer() {
        console.log("업무 중");
    },
    design() {
        console.log("업무 중");
    }
}
  • 에러

 

🛠 타입이 포함관계일 때 : Ok or Error

type Developer = {
    output: number; // ** 
    developer: () => void;
}

type Designer = {
    output: string | number; // ** 
    design: () => void;
}

const 개자이너: Developer & Designer = {
    // output: 'sth cool', // error
    output: 1, // ok (string | number) & number 이라서 number type은 ok!
    developer() {
        console.log("업무 중");
    },
    design() {
        console.log("업무 중");
    }
}
  • (string | number) & number이라서 number type은 ok!

 

🏷 요약

  • Intersection → And : A & B : A타입이면서 B타입
  • Union → Or : A | B : A타입, B 타입 둘 중 하나
반응형