Typescript 이쁘게 정리하기(3)

junghan·2022년 11월 20일
0

typescript 다루기

목록 보기
3/4
post-thumbnail

polomorphism을 마지막으로 글 작성을 마무리하려 했으나, 기존 프로젝트를 사용할 때, 절차지향적으로 코드를 작성한 것 같아 좀 더 객체지향적으로 코드를 작성할 수 있도록 클래스를 넣어 코드를 리펙토링해보려합니다. C++을 배울 때 학습하던 개념과 거의 동일한데, 복습하는 느낌으로 정리해놓으려고 합니다.

Class

typescript의 클래스의 정의방식은 매우 간단합니다. private, public, protected라는 접근지정자를 가지는 속성과 메소드를 정의가능 하고, 생성자를 통해 인스턴스를 생성할 수 있습니다. (Javascript에는 접근지정자 개념이 없는 것으로 알고 있습니다.)
javascript는 Garbage Collection에 의해 쓸모 없어진 객체 즉, 참조되지 않는 객체가 차지하는 메모리를 자동으로 해제하므로 소멸자 개념이 필요하지 않습니다.

class Player {
  constructor(
    private firstName: string,
    private lastName: string,
    public nickname: string
  ) {}
}

const junghan = new Player("jung", "han", "중한");

junghan.nickname; // O

junghan.firstName; //  X

아래와 같은 식으로도 선언 가능합니다

class Player {
  private firstName: string;
  private lastName: string;
  public nickname: string;
  constructor() {
    (this.firstName = ""), (this.lastName = ""), (this.nickname = "");
  }
}

  constructor(firstName: string, lastName: string, nickname: string) {
    (this.firstName = ""), (this.lastName = ""), (this.nickname = "");
  }

상속

user를 상속받는 player클래스를 정의하였습니다. 아래와 같이 User클래스를 가지는 속성을 그대로 상속받아 사용할 수 있습니다. 아래에서 조금 더 자세하게 다루겠지만 상속을 할 시, 부모의 클래스에 abstract를 붙여 추상 클래스로 만들면 클래스관계를 구분짓기 조금 더 편할 것 같네요.

abstract class User {
  constructor(
    private firstName: string,
    private lastName: string,
    public nickname: string
  ) {}
}

class Player extends User {}

const junghan = new User("jung", "han", "중한"); // X

const junghan = new Player("jung", "han", "중한"); // O


상속 메소드

상속받은 자식클레스에서 메소드를 추가하거나 기존 메소드를 오버라이딩할 수 있습니다.
메소드 또한 접근지정자를 사용할 수 있으며, private일 경우 인스턴스에서 사용이 불가합니다.

class User {
  constructor(
    private firstName: string,
    private lastName: string,
    public nickname: string
  ) {}
  getFullName() {
    return `${this.firstName} ${this.lastName}`;
  }
}

class Player extends User {
  getNickName() {
    return this.nickname;
  }
}

const junghan = new Player("jung", "han", "중한");

junghan.getFullName();
junghan.getNickName(); 

추상 클래스

위에서 잠시 언급한 추상클래스는 독특한 메소드를 가질 수 있습니다. 직접 인스턴스를 가질 수 없는 특성과 더불어, 자신의 클래스 내부에서 직접 구현할 수 없는 추상 메소드를 만들 수 있습니다. 아래와 같이 메소드를 직접 구현하지 않고 call signature만 적어 정의만 가능합니다.
자식 클래스에서 메소드를 재정의하면서 변수를 가져다 쓰고 싶다면, private가 아닌 protected로 선언해야겠네요. private와 마찬가지로 인스턴스 단에서 접근은 막고 클래스에서는 접근이 가능하게 되기 때문이죠.

abstract class User {
  constructor(
    private firstName: string,
    private lastName: string,
    protected nickname: string
  ) {}
  abstract getNicname(): void;
  getFullName() {
    return `${this.firstName} ${this.lastName}`;
  }
}

class Player extends User {
  getNicname() {
    return this.nickname;
  }
}

const junghan = new Player("jung", "han", "중한");

junghan.getFullName(); // private X

Type

타입정의는 객체, 숫자, 키워드 함수 등 많은 타입을 사용자 정의할 수 있도록 도와주는 방법입니다.
아래와 같이 []를 이용한 딕셔너리 형대로 저장하면 정의되지 않은 키값을 받는 객체도 손쉽게 구성이 가능합니다.

type Name = {
  [name: string]: string;
};

type age = 1 | 10 | 20;

type name = "han" | "kim" | "lee";


let name: UserInfo = {};

name["first"] = "jung";
name["last"] = "han";

interface

interface란 객체의 모양을 특정할 수 있도록 도와주는 방법입니다. 키워드를 조합하거나 튜플 함수등을 정의할 수 있는 Type과는 달리 객체만을 정의하며, class와 유사하게 사용할 수 있습니다. (추상 클래스는 js로 컴파일 시, class를 유지하며 변환되지만 interface는 사라집니다.)

interface User {
  firstName: string;
  lastName: string;
  sayHi(name: string): string;
  fullName(): string;
}

interface Human { //이미 존재하는 인터페이스에 중복하여 정의 가능 (타입은 x)
  health: number;
}

interface Human {
  health: number;
}

class Player implements User, Human {
  //두개의 인터페이스 상속가능
  constructor(
    public firstName: string, //private, protected 사용불가
    public lastName: string,
    public health: number,
    public height: number,
  ) {}
  fullName(): string {
    return `${this.firstName} ${this.lastName}`;
  }
  sayHi(name: string): string {
    return `Hi ${name}, my name is ${this.fullName()}`;
  }
}

const player: Player = { //클래스와 달리 new로 할당하지 않아도 
  firstName: "",         //객체의 형태만 맞춰 주면 사용가능
  lastName: "",
  health: 0,
  fullName: () => "1",
  sayHi: () => "2",
};

💁‍♂️ 객체를 정의할 때는 interface 그 외 모든 정의는 type을 사용하는 것이 유리하다!

ref: https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#differences-between-type-aliases-and-interfaces
https://nomadcoders.co/typescript-for-beginners

profile
42seoul, blockchain, web 3.0

0개의 댓글