Typescript - 클래스

런던행·2020년 6월 24일
0

TypeScript(기초)

목록 보기
3/4
// class

type Color = 'Black' | 'White'
type FileName = 'A' | 'B' | 'C'
type Rank = 1 | 2 | 3 | 4 | 5  // 리터럴로 직접 열거

class Position {
  constructor(
    private file: FileName, // 생성자의 private 접근 한정자는 자동으로 매개변수 this에 할당
    private rank: Rank
  ) { }

  distanceForm(position: Position) {
    return {
      rank: Math.abs(position.rank - this.rank),
      file: Math.abs(position.file.charCodeAt(0) - this.file.charCodeAt(0))
    }
  }
}

abstract class Piece {
  protected position: Position
  constructor(
    private readonly color: Color,
      file: FileName,
      rank: Rank
  ) {
    this.position = new Position(file, rank)
  }

  movoTo(position: Position) {
    this.position = position
  }

  abstract canMoveTo(position: Position): boolean
}

class King extends Piece {
  canMoveTo(position: Position) {
    let distance = this.position.distanceForm(position)
    return distance.rank < 2 && distance.file < 2
  }
}

class Game {
  private pieces = Game.makePieces()

  private static makePieces() {
    return [
      // new King('White', 'E', 1), E값이 없으므로 에러
      new King('White', 'A', 1)
    ]
  }
}

// super
// super로 부모 클래스의 메서드만 접근 가능


// 5.3 this를 반환 타입으로 사용하기

class Set2{
  has(value: number): boolean {
    return false
  }
  add(value: number): this {
      return this
  }
}

class MutableSet extends Set2 {
  delete(value: number): boolean {
    return false
  }

  // add(value: number): MutableSet { // add(): this라고 선언하면 따로 오버라이딩 안해도 된다.
  // }
}

let set = new Set2
set.add(1).add(2).add(3)
set.has(2)


// 5.4 인터페이스
// 선언 합침
// 같은 이름으로 정의된 여러 정의를 자동으로 합치는 기능
interface User {
  name: string
}

interface User {
  age: number
}

let a: User = {
  name: 'Ashley',
  age: 30
}

// 구현

interface Animal {
  readonly nmae: string // 가시성 한정자 private, protected, public는 선언 할 수 없다. static 키워드도 사용 할 수 없다.
  eat(food: string): void
  sleep(hours: number): void
}

interface Feline {
  meow(): void
}

class Cat implements Animal, Feline {
  eat(food: string) {
  }
  sleep(hours: number) {
  }

  meow() {

  }
}


// 클래스는 구조기반 타입을 지원한다. 

class Zebra {
  trot() {
    //..
  }
}

class Poodle {
  trot() {
    //...
  }
}

function ambleAround(animal: Zebra) {
  animal.trot()
}

let zebra = new Zebra
let poodle = new Poodle

ambleAround(zebra) // its ok
ambleAround(poodle) /. it osk


// 클래스는 값과 타입을 모두 선언한다. 
let a = 1999
function b() {}
type a = number
interface b {
  (): void
}

if (a + 1 > 3) ; // let a
let x: a = 3 // type a

class C {}
let c: C = new C
enum E { F, G }
let e: E = E.F

type State = {
  [key: string]: string
}

class StringDatabase {
  state: State = {}
  get(key: string): string | null {
    return key in this.state ? this.state[key] : null
  }
  set(key: string, value: string): void {
    this.state[key] = value
  }
  static from(state: State) {
    let db = new StringDatabase
    for (let key in state) {
      db.set(key, state[key])
    }
    return db
  }
}


interface StringDatabase {
  state: State
  get(key: string): string | null
  set(key: string, value: string): void
}

interface StringDatabaseConstructor {
  new(): StringDatabase  // 생성자 시그니쳐
  from(state: State): StringDatabase
}

// 다형성

class MyMap<K, V> {
  constructor(initialKey: K, initialValue: V) {

  }
  get(key: K): V {

  }
  set(key: K, value: V): void {

  }
  merge<K1, V1>(map: MyMap<K1, V1>): MyMap<K | K1, V | V1> {

  }

  static of<K, V>(k: K, v:V): MyMap<K, V> {

  }
}
// 인터페이스에도 제네릭을 사용 할 수 잇다.
interface MyMap<K, V> {
  get(key: K): V
  set(key: K, value: V): void
}

// 함수와 마찬가지로 제네릭에 구체타입을 명시하거나 타입스크립트가 타입을 추론 할 수 있다.
let a = new MyMap<string, number>('k', 1)  // MyMap<string, number> 
let b = new MyMap('k', true)               // MyMap<string, boolean>

// 믹스인
// 믹스인이란 동작과 프로퍼티를 클래스로 혼합(mix)할 수 있게 해주는 패턴으로 다음 규칙을 따른다
// 상태를 가질 수 있다 - 인스턴스 프로퍼티
// 구체 메서드만 제공할 수 있다
// 생성자를 가질 수 있다.

type ClassConstructor = new (....args: any[]) => {}

function withEZDebug<C extends ClassConstructor>(Class: C) {
  return class extends Class {
    debug() {
      let name = this.constructor.name
      let value = this.getDebugValue()
      return Name + '(' + JSON.stringify(value) + ')'
    }
  }
}

// Decorator 는 타입스크립트에서 실험용이다.

// final 클래스 흉내내기
// 비공개 생성자(private constructor)로 final 클래스를 흉내 낼 수 있다. 
class MessageQueue {
  private constructor(private messages: string[]) {
  }
}


// 디자인 패턴
// 팩토리 패턴

type Shoe = {
  purpose: string
}

class BalletFlat implements Shoe {
  purpose: 'dancing'
}

class Boot implements Shoe {
  purpose: 'woodcutting'
}

let Shoe = {
  create(type: 'balletFalt' | 'boot'): Shoe {
    switch (type) {
      case 'balletFalt': return new BalletFalt
      case 'boot': return new Boot
    }
  }
}

Shoe.create('boot') // Shoe


// 빌더 패턴
// 빌더 패턴으로 객체의 생성과 객체 구현 방식을 분리 할 수 있다.

class RequestBuilder {
  private data: object | null = null
  private method: 'get' | 'post' | null = null
  private url: string | null = null

  setMethod(method: 'get' | 'post') : this {
    this.method = method
    return this
  }
  setData(data: object): this {
    this.data = data
    return this
  }
}```
profile
unit test, tdd, bdd, laravel, django, android native, vuejs, react, embedded linux, typescript

0개의 댓글