리터럴 타입 / 유니온 타입 / 교차 타입

최형용·2023년 2월 19일
0

리터럴 타입(Literal Types)

변수 혹은 매개변수 등이 string이나 number처럼 어떠한 포괄적인 타입을 가지는 것이 아니라 변수나 매개변수에 정확한 값을 설정하는 것이다.

문자열 리터럴 타입(String Literal Types)

//아래 코드에서 Food에서 허용한 3개의 문자열 외에 다른 문자열을 사용하게 되면 에러가 발생한다.
type Food = "rice" | "noodle" | "meat";

const myFood1: Food = "rice";
const myFood2: Food = "aaa";  // Error: Type 'aaa' is not assignable to type 'Food'.

숫자 리터럴 타입(Numeric Literal Types)

type Grade = 1 | 2 | 3;
const student1: Grade = 1;
const student2: Grade = 5; // Error: Type '5' is not assignable to type 'Grade'.

리터럴 타입 좁히기(Literal Narrowing)

var, let으로 변수를 선언하면 이 변수의 값이 변경될 가능성이 있음을 컴파일러에게 알린다. 반면, const를 사용해서 변수를 선언하면 값이 절대 변하지 않는다는 것을 컴파일러에게 알린다.

// const를 사용해서 변수가 절대 변경되지 않음을 보장한다.
const helloWorld = "Hello World";

// let은 변경될 수 있으므로 컴파일러는 문자열이라고 선언 할 것이다.
let helloWorkd = "Hello World";

유니온 타입(Union Type)

유니온 타입(Union Type)이란 자바스크립트의 OR 연산자(||)와 같이 'A' 이거나 'B'이다라는 의미의 타입이다.

//함수의 파라미터 text에는 문자열 타입이나 숫자 타입이 모두 올 수 있다.
//이처럼 | 연산자를 이용하여 타입을 여러 개 연결하는 방식을 유니온 타입 정의 방식이라고 부른다.

function logText(text: string | number) {
  // ...
}

공통 필드를 갖는 유니온

이 예제에서, Bird는 fly라는 멤버를 갖고 있다. Bird | Fish로 타입이 지정된 변수가 fly
메서드를 가지고 있는지 확신할 수 없다. 만약 변수가 실제로 런타임에 Fish이면, pet.fly()
를 호출하는 것은 오류이다.

interface Bird {
  fly(): void;
  layEggs(): void;
}

interface Fish {
  swim(): void;
  layEggs(): void;
}

declare function getSmallPet(): Fish | Bird;

let pet = getSmallPet();
pet.layEggs();

// 두 개의 잠재적인 타입 중 하나에서만 사용할 수 있습니다.
pet.swim(); //error

유니온 구별하기

유니언을 사용하는 데 있어서 일반적인 기술은 TypeScript가 현재 가능한 타입 추론의 범위를 좁혀나가게 해줄 수 있는 리터럴 타입을 갖는 단일 필드를 사용하는 것이다.
state 필드가 NetworkState 안의 모든 타입에 공통으로 존재한다는 점을 안다면 존재 여부를 체크하지 않고도 접근할 수 있다.

type NetworkLoadingState = {
  state: "loading";
};

type NetworkFailedState = {
  state: "failed";
  code: number;
};

type NetworkSuccessState = {
  state: "success";
  response: {
    title: string;
    duration: number;
    summary: string;
  };
};

type NetworkState =
  | NetworkLoadingState
  | NetworkFailedState
  | NetworkSuccessState;

function networkStatus(state: NetworkState): string {
  // 현재 TypeScript는 셋 중 어떤 것이
  // state가 될 수 있는 잠재적인 타입인지 알 수 없습니다.

  // 모든 타입에 공유되지 않는 프로퍼티에 접근하려는 시도는
  // 오류를 발생시킵니다.
  state.code;

  // state에 swtich문을 사용하여, TypeScript는 코드 흐름을 분석하면서
  // 유니언 타입을 좁혀나갈 수 있습니다.
  switch (state.state) {
    case "loading":
      return "Downloading...";
    case "failed":
      // 여기서 타입은 NetworkFailedState일 것이며,
      // 따라서 `code` 필드에 접근할 수 있습니다.
      return `Error ${state.code} downloading`;
    case "success":
      return `Downloaded ${state.response.title} - ${state.response.summary}`;
  }
}

교차 타입(Intersection Type)

교차 타입(Intersection Type)은 여러 타입을 모두 만족하는 하나의 타입을 의미한다.
예를 들어 type D = A & B & C & 와 같은 타입을 정의하면 D는 A, B , C의 속성 모두를 가진다.

interface Person {
    name: string;
    age: number;
}

interface Developer {
    name: string;
    skill: number;
}

type Capt = Person & Developer;

let person: Capt = {
    name : "tony",
    age : 5,
    skill: 5
}

교차 타입 주의할 점

교차 타입의 경우 동일한 키 값의 서로 다른 타입이 있는 경우 never 타입으로 바꿔버리는 것을 볼 수 있다.

type Animal1 = {
  howl: number;
};
type Animal2 = {
  howl: string;
};

type animal1 = Animal1 | Animal2;
type animal2 = Animal1 & Animal2;

let test1: animal1 = {
  howl: "animallll",
};

// error : 'number' 형식은 'never' 형식에 할당할 수 없습니다.
let test2: animal2 = {
  howl: 123
};
profile
꾸준한 개발자가 되고 싶습니다

0개의 댓글