5/5(목) - TypeScript Class -2

길고 꾸준하게·2022년 5월 5일
0

TypeScript퍼먹기

목록 보기
5/6
post-thumbnail

1. 추상클래스 & interface

추상클래스는 추상클래스를 상속할 클래스들의 청사진을 정해주는 느낌이라고 어제 배웠다.
하지만 JavaScript로 컴파일된 모습을 보면.

//in TypeScript

abstract class Exam{
  constructor(
    public foo:string,
    public bar:string
  ){}

  abstract absMethod():string //추상 메서드
}

class Exam2 extends Exam{ //추상클래스로는 인스턴스객체를 만들수없음.
  absMethod(){
    return 'abstract methods' //추상메서드는 반드시 같이 가야됨(청사진을 따라야지)
  }  
}

const instanceObj = new Exam2('a','b')
console.log(a.foo)
console.log(a.bar)
//in JavaScript

"use strict";
class Exam {
    constructor(foo, bar) {
        this.foo = foo;
        this.bar = bar;
    }
}
class Exam2 extends Exam {
    absMethod() {
        return 'abstract methods';
    }
}
const a = new Exam2('a', 'b');
console.log(a.foo);
console.log(a.bar);

보면 '청사진'의 용도로 만든 추상클래스 Exam이 JS에서 클래스로 떡하니 컴파일되서 파일용량을 차지하고있는걸 볼수있다. 이를 해결할수있는게 interface

Interface

Type Alias와는 다른 타입선언 방법. JavaScript에도 룰이 있는것처럼 TypeScript에도 있는데.

Object나 Class의 타입선언은 interface, 그외는 Type Alias로 한다.

그렇다고 한다. interface를 사용해서 추상클래스를 구현하면 JS에선 어떤모습일까?

//in TypeScript

interface User{
  firstName:string
  lastName:string
  sayHi(name:string):string
  getFullName():string
}
interface Human{
  bloodType:string
}
class Player implements User,Human{
  constructor(
    public firstName:string,
    public lastName:string,
    public bloodType:string
  ){}
  sayHi(name:string){
    return `my name is ${name}`
  }
  getFullName(){
    return `${this.firstName} ${this.lastName}`
  }
}
//in JavaScript
"use strict";
class Player {
    constructor(firstName, lastName, bloodType) {
        this.firstName = firstName;
        this.lastName = lastName;
        this.bloodType = bloodType;
    }
    sayHi(name) {
        return `my name is ${name}`;
    }
    getFullName() {
        return `${this.firstName} ${this.lastName}`;
    }
}

컴파일시 추상클래스(interface로 구현한)는 컴파일되지 않아서 파일용량에 영향을주지 않는걸 볼수있다. 하지만 몇가지 다른점이 있는데

  • interface로 상속을 할때는 'extneds'가 아닌 'implements'로 상속해야한다
  • interface는 접근수정자(private,protected,public 등)는 가질수 없다.
    기본적으로 public 클래스만 만든다.
    => 그래서 자식클래스에 생성자함수의 접근수정자가 public으로만 되어있는것.

Interface | Type

TypeScript공식 문서에서 있는 차이비교를 적어보자면.

Extending

// Extending an interface
interface Animal {
  name: string
}

interface Bear extends Animal {
  honey: boolean
}

//Extending a type via intersections
type Animal = {
  name: string
}

type Bear = Animal & { 
  honey: boolean 
}

Adding new fields

interface Window {
  title: string
}

interface Window {
  ts: TypeScriptAPI
}

//기존 interface에 새 fields를 추가하기만 하면 된다.
type Window = {
  title: string
}

type Window = {
  ts: TypeScriptAPI
}

 // Error: Duplicate identifier 'Window'.
 // Type은 생성된 이후 유형을 변경할수 없다.

Conclustion

interface SStorage<T>{
  [key:string]:T
}

// 이미 JS의 WebStorage API를 위한 Storage인터페이스 정의되어있어서 오버라이드를 막기위해 저렇게 지음

class LocalStorage<T>{ //keypoint
  private storage:SStorage<T>;
  
  constructor(){
    this.storage = {};
  }
  
  set(key:string,value:T){ //keypoint
    this.storage[key]=value
  }
  remove(key:string){
    delete this.storage[key]
    //javascript의 delete연산자는 객체의 속성을 제거한다(프로퍼티)
  }
  get(key:string):T{ //keypoint
    return this.storage[key]
  }
  clear(){
    this.storage = {};
  }
}

const stringsStorage = new LocalStorage<string>()
const booleanStorage = new LocalStorage<boolean>()

booleanStorage.set('key',true)
stringsStorage.set('key','value')

배움은 계속된다..

profile
작은 나의 개발 일기장

0개의 댓글