初めまして、株式会社Another works CTOの塩原です。
弊社ではフロントエンドでもサーバーサイドでもTypescriptを使っているのですが、クラスの初期化パターンでいろいろと試行錯誤して方針を決めたので今回はその試行錯誤の過程で考えたパターンを紹介できればと思います。
constructor(Partial)
class Klass {
public propertyA: string
public propertyB: string
constructor(init: Partial<Klass>) {
this.propertyA = init.propertyA || ''
this.propertyB = init.propertyB || ''
}
}
new Klass({propertyA: 'test', propertyB: 'test'})
メリット
記述量が少なくて済む
デメリット
Partialなので、確実に初期化したいものでもoptionalで渡せてしまう
constructor(Readonly)
class Klass {
public propertyA: string
public propertyB: string
constructor(init: Readonly<Klass>) {
this.propertyA = init.propertyA
this.propertyB = init.propertyB
}
}
new Klass({propertyA: 'test', propertyB: 'test'})
メリット
記述量が少なくて済む
Readonlyでは、propertyがoptionalのものとrequiredのものでそれぞれ初期化する際の引数に反映される
デメリット
Readonlyではこのクラスにメソッドが生えていた場合に、関数も引数として渡さないといけなくなる
constructor(public propertyA: string, public propertyB: string)
class Klass {
constructor(public propertyA: string, public propertyB: string) {}
}
new Klass('test', 'test')
メリット
今回の中で最も記述量が少ない
デメリット
引数の数が増えると渡す側を見た時になにが渡されているのかがわからない、渡す順番を間違えても気づきくい場合がある。(型が同じだと)
constructor(init: {propertyA: string, propertyB: string})
class Klass {
public propertyA: string
public propertyB: string
constructor(init: {propertyA: string, propertyB: string}) {
this.propertyA = init.propertyA
this.propertyB = init.propertyB
}
}
new Klass({propertyA: 'test', propertyB: 'test'})
メリット
上三つのデメリットを全てクリアしている
デメリット
記述量が多い
propertyの初期化漏れが起こるとエラーに気づけない
propertyの初期化漏れが起こるとエラーに気づけない -> strictPropertyInitializationがあった!
tsconfig.jsonでstrictPropertyInitialization: true
にすると初期化漏れがあればコンパイル時にエラーを出してくれる
strictPropertyInitialization最高!
結果
結果的に、tsconfig.jsonを設定することで、最後の書き方にしました。
他にももっといい書き方があればまた記事を更新していきます。
Another worksでは一緒に働く仲間を募集しています!