NestJS

[TypeScript] 타입스크립트 기초

개발조하 2023. 11. 5. 22:29

01. 기본 지식

  • tsc: 타입스크립트를 자바스크립트로 변환해주는 컴파일러이자, 타입을 검사해주는 역할 또한 진행해준다.
    • 이는 tsconfig.json 파일로 옵션을 넣을 수 있다.
    • 코드를 변환해주는 역할과 타입을 검사하는 역할이 별개이다.
      • 즉 타입 검사가 오류가 나더라도 코드 변환은 정상적으로 이루어진다.
    • tsc --noEmit: 타입 검사만 확인하는 명령어

02. tsc 사용하기

  • nodejs 에서 typescript 를 사용하기 위해서는 다음과 같은 명령어가 필요하다.

      $ npm init# package.json 생성
      $ sudo npm i typescript# typescript install
      $ sudo npx tsc --init# tsconfig.json 생성
    
    • 여기서 tsc 명령어를 사용하기 위해서는 앞에 npx가 필요하다. (ex. npx tsc -h)
  • tsconfig.json 파일에서 주의 깊게 봐야될 옵션

    • esModuleInterop
    • strict
    • forceConsistentCasingInFileNames: 입포트 하는 파일 이름의 대소문자 구별하도록 하는 옵션
    • skipLibCheck: 실제로 사용하고 있는 파일의₩ 타입만 확인하도록 하는 옵션

03. TypeScript 실습 (내가 몰랐던 부분들만 정리)

03-01. 타입 자체를 정의할 수 있음. (type, interface, function)

  • type 을 통해서 Add 라는 새로운 자료형을 정의할 수 있다.

  • 예제

      //* type 을 통해서 Add 라는 새로운 자료형을 정의할 수 있다.type Add = (x: number, y: number) => number;
      const add: Add = (x, y) => x + y;
      console.log(add(3, 4));
  • interface 로도 타입을 정의하여 사용할 수 있다. (이 방법은 흔하지는 않다.)

      interface Add {
        (x: number, y: number): number;
      }
      const add: Add = (x, y) => x + y;
      console.log(3, 4);//* 7
  • 함수 자체를 미리 선언해놓을 수도 있다.

      function add(x: number, y: number): number;
      //* 위에서 타입 선언을 했을 경우에는 아래서 명시적으로 any 쓰셔도 무방하다.function add(x: any, y: any) {
        return x + y;
      }
      console.log(add(1, 2));

03-02. as 를 통해서 강제 typing 을 할 수 있다.

  • as 를 통해서 다른 타입의 값을 넣을 있다.

      let aa = 123;
      aa = "hello" as unknown as number;

03-03. never 타입

  • 항상 오류를 출력하거나 리턴 값을 절대로 보내지 않음을 의미한다.

      function invalid(message: string): never {
        throw new Error(message);
      }

03-04. ${} 으로 type 을 확장 정의가 가능하다.

  • 예제

      type world = "world" | "hello";
      type helloWorld = `hello ${world}`;
      //* 아래 두개 가능const hi_hello: helloWorld = `hello hello`;
      const hi_world: helloWorld = "hello world";

03-05. type 정의의 & 연산자

  • & 가 들어가면 양 옆에 있는 타입을 모두 만족해야 한다는 것이다. 예시는 다음과 같다.

      type A = { hello: "hello" } & { zeor: "cho" };
      const a: A = { hello: "hello", zeor: "cho" };

03-06. type 의 확장 예시

type Animal = { breath: true };
type Poyouryu = Animal & { breed: true };
type Human = Poyouryu & { think: true };

const yjyoon: Human = {
  breath: true,
  breed: true,
  think: true,
};

03-07 interface, type, enum 의 네이밍 규칙

  1. 앞에 interfaceI, typeT, enumE를 붙인다.

    • 예시:

        interface IProp {}
        type TType = string | number;
        enum EHello {
          Left,
          Right,
        }
  2. 1번 과 같은 것들을 안붙인다.

요즘에는 2번을 많이 쓴다. 이유는 커서 올리면 다 보이기 때문이다.

03-08. void 의 두가지 정체

  • void 는 형식에 따라서 아래 두개로 동작한다.

    • 함수의 return type으로 void를 설정한 경우: 함수의 반환값이 존재하지 않는다.
    • interface에 선언되어있는 메소드의 return type 또는 callback 의 return type인 경우: 함수의 반환값이 존재할 수는 있지만 이를 사용하지 않는다.
  • 예시

      function a(callback: () => void): void {}//* 이 함수의 리턴값이 없어야 한다.a(() => {
        return "3"; //* callback 함수의 return 이 void 이지만 여기서 return 값이 있어도 상관없다.
      }){};
    
      interface Human {
        talk: () => void;
      }
    
      const human: Human = {
        talk() {
          return "abs";//* interface에서 talk 메소드의 리턴 타입이 void. 하지만 return 값이 존재해도 상관없다.
        },
      };

03-09 type guard 기법

  • 어떤 변수의 타입을 체크하는 로직 구현 기법

      function numOrStr(a: number | string) {
      //* a.toFixed(1) --> 에러 발생 (string 일때는 사용할 수 없기 때문)if (typeof a === "number") {
      //* Type Guard
          a.toFixed(1);
        } else if (typeof a === "string") {
          a.charAt(3);
        }
      }
    
      numOrStr("123");
      numOrStr(1);
  • class 의 경우에 type Guard 를 instanceof 확용하여 확인한다.

      class A {
        aaa() {}
      }
      class B {
        bbb() {}
      }
    
      function aOrB(param: A | B) {
        if (param instanceof A) {
          param.aaa();
        } else if (param instanceof B) {
          param.bbb();
        }
      }
  • type guard 는 커스텀해서 만들 수 있다.

      interface Cat {
        meow: number;
      }
      interface Dog {
        bow: number;
      }
    
      //* 커스텀 타입 가드 (return type 으로 is 를 쓴다.)
      function catOrDog(a: Cat | Dog): a is Dog {
        if ((a as Cat).meow) {
          return false;
        }
        return true;
      }
    
      function pet(a: Cat | Dog) {
        if (catOrDog(a)) {
          console.log(a.bow);
        } else {
          console.log(a.meow);
        }
      }

03-10 Object vs {} (4.8 버전 이후)

  • Object, {}: 모든 타입을 의미한다. (null과 undefined 는 제외)
  • unknown을 if 문 안에 넣으면 해당 변수의 타입은 {}이 된다.

03-11 implemenets

  • implements 는 형식을 정의해주는 것이다.

      interface A {
        a: string;
        b: string;
      }
    
      class B implements A {
        b: string = "asd";
        a: string = "1";
      }
    • 위 코드에서 B class 는 A에 정의된 a,b를 모두 구현해놔야 한다.

03-12 제네릭

  • 타입을 변수처럼 만드는 것 (아 타입 지금은 모르겠고~ 나중에 정할게~)
function add<T extends string>(x: T, y: T): T {
  return x + y;
}
add(1, 2);
add("1", "2");

// <T extends {...}> // 특정 객체
// <T extends any[]> // 모든 배열
// <T extends (...args: any) => any> // 모든 함수
// <T extends abstract new (...args: any) => any> // 생성자 타입
// <T extends keyof any> // string | number | symbol