// 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
}
}```