[TypeScript] クラス2

### インターフェイス

interface Human {
    name:string
    print():void
}

class Person implements Human {
    name:string = 'no-name'
    mail:string
    age:number

    constructor(name:string, mail:string = 'no-mail', age:number = -1){
        this.name = name
        this.mail = mail
        this.age = age
    }

    print():void {
        console.log(this.name + '(' + this.mail + ',' + this.age + ')')
    }
}

class Student implements Human {
    name:string = 'no-name'
    school?:School
    grade?:number

    constructor(name:string,school?:School, grade?:number){
        this.name = name
        this.school = school
        this.grade = grade
    }

    print():void {
        let gd:string = this.grade ? String(this.grade) : '-'
        console.log(this.name + '(' + this.school + ' school: ' + gd + ' grade)') 
    }
}

const taro:Person = new Person('taro', 'taro@yamada', 39)
const hanako:Student = new Student('hanako', School.high, 39)
const sachiko:Person = new Person('sachiko')
const jiro:Student = new Student('jiro')

const data:Human[] = [taro, hanako, sachiko, jiro]

for(let item of data){
    item.print()
}

### インターフェイスの継承

interface People extends Human {
    birth:Date
}

class Employee implements People {
    name:string = 'no-name'
    company:string = ''
    birth:Date = new Date()

    constructor(nm:string, cm:string, bth:Date){
        this.name = nm
        this.company = cm
        this.birth = bth
    }

    print():void {
        console.log(this.name + ' [' + this.company + ']')
    }
}

const ichiro = new Employee('ichiro',
    'Baseball Inc.', new Date('1982/10/10'))
ichiro.print()

### 静的メンバー

class StaticHuman {
    static fullname:string
    static age:number
    
    static set(nm:string, ag:number):void {
        this.fullname = nm
        this.age = ag
    }

    static print():void {
        console.log(this.fullname + '(' + this.age + ')')
    }
}

StaticHuman.set('taro',39)
StaticHuman.print()
StaticHuman.set('hanako',29)
StaticHuman.print()

### パラメータープロパティ

class Human {
    constructor(readonly name:string, readonly age:number){

    }

    print():void {
        console.log(this.name + '(' + this.age + ')')
    }
}

const taro = new Human('taro', 39)
taro.print()
const hana = new Human('hanako', 28)
hana.print()

### 総称型

class Data<T> {
    data?:T[]

    constructor(...item:T[]){
        this.data = item
    }

    print():void {
        if(this.data) {
            for(let item of this.data){
                console.log(item)
            }
        } else {
            console.log('no data...')
        }
    }
}

const data1 = new Data<string>('one','two','three')
const data2 = new Data<number>(123,456,78,90)
data1.print()
data2.print()

### ユーティリティ型
Readonly, Required, Partial

type Human = {
    name:string
    mail?:string
    age?:number
}

class Person {
    human:Required<Human>

    constructor(nm:string, ml:string, ag:number){
        this.human = {name:nm, mail:ml, age:ag}
    }

    print():void {
        console.log(this.human.name
            + ' (' + this.human.age + '::'
            + this.human.mail + ')')
    }
}
const taro = new Person('taro', 'taro@yamada', 39)
taro.print()

OK