Dandy Now!
  • [TypeScript] 고급타입(udemy 강의 "Typescript :기초부터 실전형 프로젝트까지 with React + NodeJS" 섹션 6)
    2024년 03월 10일 23시 08분 54초에 업로드 된 글입니다.
    작성자: DandyNow
    728x90
    반응형

    섹션 6: 고급타입

    📌 인터섹션 타입

    1. type과 &

    type Admin = {
      name: string;
      privileges: string[];
    };
    
    type Employee = {
      name: string;
      startDate: Date;
    };
    
    type ElevatedEmployee = Admin & Employee; // 두 타입의 속성 모두 사용 가능
    
    const e1: ElevatedEmployee = {
      name: "김일남",
      privileges: ["create-server"],
      startDate: new Date(),
    };

     

    2. interface와 extends

    interface AdminInter {
      name: string;
      privileges: string[];
    }
    
    interface EmployeeInter {
      name: string;
      startDate: Date;
    }
    
    interface ElevatedEmployeeInter extends Admin, Employee {}
    
    const e2: ElevatedEmployeeInter = {
      name: "김일남",
      privileges: ["create-server"],
      startDate: new Date(),
    };

     

    3. | 와 &

    type Combinable = string | number;
    type Numeric = number | boolean;
    
    type Universal = Combinable & Numeric; // 유니언 타입을 인터섹션 타입으로 적용하는 경우 교차하는 number 타입만 사용 가능
    
    const e2: Universal = 99;

     

    📌 타입 가드

    런타임 시 특정 타입으로 작업을 수행하기 전에 해당 타입을 검사하는 코드 패턴

    1. in

    type Admin = {
      name: string;
      privileges: string[];
    };
    
    type Employee = {
      name: string;
      startDate: Date;
    };
    
    type UnknownEmployee = Employee | Admin;
    
    function printEmployeeInformation(emp: UnknownEmployee) {
    
      console.log("Name: " + emp.name);
      
      // in 사용
      if ("privileges" in emp) {
        console.log("Privileges: " + emp.privileges);
      }
      if ("startDate" in emp) {
        console.log("Start Date: " + emp.startDate);
      }
    }
    
    printEmployeeInformation({ name: "김일남", startDate: new Date() });
    
    /* 출력 결과
    Name: 김일남
    Start Date: Sun Mar 10 2024 22:59:59 GMT+0900 (한국 표준시)
    */

     

    2. instanceof

    class Car {
      drive() {
        console.log("Driving...");
      }
    }
    
    class Truck {
      drive() {
        console.log("Driving a truck...");
      }
    
      loadCargo(amount: number) {
        console.log("Loading cargo ..." + amount);
      }
    }
    
    type Vehicle = Car | Truck;
    
    const v1 = new Car();
    const v2 = new Truck();
    
    function useVehicle(vehicle: Vehicle) {
      vehicle.drive();
      // instanceof 사용
      if (vehicle instanceof Truck) {
        vehicle.loadCargo(1000);
      }
    }
    
    useVehicle(v1); 
    /* 출력 결과
    Driving...
    */
    
    useVehicle(v2);
    /* 출력 결과
    Driving a truck...
    Loading cargo ...1000
    */

     

    📌 구별된 유니언(Discriminated Union)

    유니언 타입을 대상으로 타입 가드를 구현할 때 도움이 되는 패턴

    interface Bird {
      type: "bird"; // 리터럴 타입 이용, 원하는 속성명 사용 가능
      flyingSpeed: number;
    }
    
    interface Horse {
      type: "horse";
      runningSpeed: number;
    }
    
    type Animal = Bird | Horse; // 유니언 타입
    
    function moveAnimal(animal: Animal) {
      let speed;
      switch (animal.type) {
        case "bird":
          speed = animal.flyingSpeed;
          break;
        case "horse":
          speed = animal.runningSpeed;
      }
    }
    
    moveAnimal({ type: "bird", flyingSpeed: 10 });

     

    📌 형변환

    <> 또는 as를 사용해 타입 스크립트에게 HTML 요소 타입임을 알려줌

    // case 1
    const userInputElement = <HTMLInputElement>(
      document.getElementById("user-input")! // "!"는 document.getElementById("user-input")가 null이 아님을 의미
    );
    
    // case 2
    const userInputElement = document.getElementById(
      "user-input"
    ) as HTMLInputElement;
    
    userInputElement.value = "Hi there!";

     

    📌 인덱스 속성

    // case1: string 타입인 경우
    interface ErrorContainer {
      [prop: string]: string;
    }
    
    const errorBag: ErrorContainer = {
      email: "Not a valid email!",
      userName: "Must start with a capital character!",
    };
    
    const errorBagNumberKey: ErrorContainer = {
      1: "Not a valid email!", // string 타입인 경우 문자, 숫자 가능
      2: "Must start with a capital character!",
    };
    
    
    // case2: number 타입인 경우
    interface numberContainer {
      [prop: number]: string;
    }
    
    const numberKey: numberContainer = {
      1: "Not a valid email!",
      userName: "Must start with a capital character!", // number 타입인 경우 문자는 에러!!!
    };

     

    📌 함수 오버로드

    type Combinable = string | number;
    
    function add(a: number, b: number): number;
    function add(a: string, b: string): string;
    function add(a: string, b: number): string;
    function add(a: number, b: string): string;
    function add(a: Combinable, b: Combinable) {
      // 분기문으로 반환 타입을 구별해 주어야 한다.
      if (typeof a === "string" || typeof b === "string") {
        return a.toString() + b.toString();
      }
      return a + b;
    }
    
    console.log(add(1, "A")); // 1A
    console.log(add("1", "A")); // 1A
    console.log(add(1, 2)); // 3

     

    728x90
    반응형
    댓글