티스토리 뷰

타입스크립트 4.8 업데이트에 추가된 타입

  • {}
  • Object (대문자로 시작) 
-> 이 두가지 타입은 모든 타입을 가리키며 모든 값을 받을 수 있다. (null과 undefined는 제외)
unknown도 any와 마찬가지로 모든 값을 받을 수 있는데 unknown이 4.8버전부터 {} | null | undefined 와 같이 성립되기 때문에 조건문에 들어갔을 때 아래와 같이 된다. 
const z: unknown = "hi"; //모든 타입이 들어가기 때문에 hi도 들어갈 수 있다.
  if (z) {
    z; //z의 타입이 {}이다. 파라미터로 들어온 z 는 unknown인데 true일때는 {}인 것
  } else {
    z; //unknown
  }

실제로 객체 타입은 object가 있는데 string의 원시값을 넣으면 에러가 뜬다. object와 Object는 다르다. 

-object는 지양해야하는 타입이므로 interface나 type, class 활용해야 한다. 

const x: {} = "hello";
const y: Object = "hihi";
const xx: object = {
    hello: "world",
  };
  //   const yy: object = "string"; object 타입에 string이라는 원시값 대입X
  
const z :unknown= "hi"; //unknwon타입도 모든 값을 받을 수 있다.

인덱스드 시그니처

객체의 키타입과 키값의 타입을 공통으로 지정하고 싶을 때 사용한다.

type A = { [key: string]: string };

맵드 타입스

위의 타입에서 키를 더 좁혀서 사용할 수 있다. in 키워드 사용

interface로는 |(또는)이 안되기 때문에 union을 사용할 때에는 무조건 type으로 써야 한다. ( & intersection도 인터페이스에서 안된다. 그래서 type 사용 )
type B = "Human" | "Mammal" | "Animal";
type A = { [key in B]: string };
const a: A = { Human: "cong", Animal: "cong", Mammal: "cong" };

 type C = { [key in B]: B }; //이런 식으로 값도 타입으로 지정해줄 수 있다.
 const c: C = { Animal: "Animal", Mammal: "Human", Human: "Mammal" };

클래스 추가 정리

  • constructor(생성자)를 쓰는 이유는 new연산자로 인스턴스를 생성하기 위함이다.
  • 클래스의 이름은 그 자체로 타입이 될 수는 있지만 클래스 자체를 가리키는 것이 아니라 new연산자를 통해 생성된 해당클래스의 인스턴스이다. 클래스 자체는 :typeof A 라고 입력해야 한다. 
class A {
    a: string;
    b: number;

    constructor(a: string, b: number = 123) {
      this.a = "123";
      this.b = 123;
    }

    method() {}
  }
  const a1 = new A("안녕"); // number에 기본값으로 123을 설정해놨기 때문에
  // 인수로 string 하나만 넘겨줘도 에러가 나지않는다. 당연히 b의 앞에 ?: number 이런식으로 처리하지 않아도된다.

  type AA = A;
  const a: A = new A("123", 223); //:A 는 클래스로 생성된 인스턴스를 지칭
  const b: typeof A = A; // :typeof A 는 클래스 자체를 가리킨다.
JS에서 클래스 내부에서만 사용할 수 있는 프로퍼티를 #로 프라이빗하게 지정할 수 있는데, TS자체에서도 private 키워드를 제공한다. private 외에도 protected 라는 키워드를 제공하기 때문에 TS 키워드로 클래스의 속성을 보호하는 것을 추천한다.
class A {
    private a: string = "123"; //권장 private syntax from TS
    #b: number = 123; // 비권장 private syntax from JS

    // constructor(a: string, b: number = 123) {
    //   this.a = "123";
    //   this.b = 123;
    // }

    method() {
      console.log(this.a, this.#b);
    }
  }
  const aaa: A = new A();
  console.log(aaa); 
/*
  A: {
  "a": "123"
  } 
*/
implements / private / protected / public(디폴트라 안써도 됨)는 TS에만 있는 문법이며 interface의 속성을 class에서 구현해야 할 때 implments 키워드를 사용한다. 즉, class의 모양을 interface를 통해 통제할 수 있다.) 
*자바 문법을 아신다면 이해하기 쉬울 듯
  • 인스턴스에서 접근되는 것이 public이다. -> 일반 속성
  • private은 class 내부에서만 접근 가능 (인스턴스에서 x, 상속 클래스에서도 x)
  • protected는 인스턴스에서 사용 불가능 (private과 차이점은 상속 extends를 통해 상속한 "상속 클래스"에서도 접근가능하다.
class B implements A {
    //즉 A인터페이스에 있는 a b 속성을 class B에서 구현해야 함
    private a: string = "123";
    protected b: string = "world";
    c: string = "hihi";
  }
  class C extends B {
    classCMethod() {
      // console.log(this.a);
      console.log(this.b);
      console.log(this.c);
    }
  }
  // new C().b;
  new C().c;
💥인터페이스를 통해서 class 를 구현하느냐 그냥 class에서 바로 구현하느냐는 추상과 구현부를 구분하여 객체지향 프로그래밍을 할 것인가와 js로 변환 시 해당 코드를 남길 것이냐(class는 interface와 다르게 js변환 시에도 남아있기 때문에)를 기준으로 개인의 취향껏 사용하면 된다. 사실상 TS에서는 interface 가 하는 역할인 추상 부분을 abstract class와 abstract method(추상클래스, 추상메서드)로 상속 시(extends) 구현을 강제할 수 있기 때문에 굳이 interface를 사용하지 않아도 된다. 

 

 

 

- 여담

이전에 자바 문법을 공부한 적이 있어서 이 개념이 그렇게 어렵게 다가오지는 않았다. 하지만 처음 접하는 사람이라면 헷갈릴 거 같다🤔

댓글