typescriptでscalaのcase class#copyみたいなことがしたい


普段Scalaを書いている時にはcase class無しでは生きられないくらいお世話になっているわけですが、typescriptでもimmutableなcase classっぽいものを使いたいのです。

classをimmutableにするだけならコンストラクタ引数を全部`public readonlyにすれば良いだけなので簡単です。

class User {
  constructor(
    public readonly id: number,
    public readonly name: string,
    public readonly age: number
  ) {}
}

楽勝!
でもこれだけじゃ足りない。copyメソッドも欲しい!どうしたものか。。。

と、考えた結果Partialを使って自前実装するのが良いんじゃないかという結論にたどり着きました。

  // 名前がcopyでないのは好みの問題です
  public cloneWith(v: Partial<User>) {
    return new User(
      this.id,
      v.name || this.name,
      v.age || this.age,
    )
  }

なにげにidは置き換え不可とかの制御ができるのも良いところだと思います。

問題があるとしたらコンストラクタ引数が増えるとそれに合わせてcloneWithの方も直さないといけないのでタイプ量が増えるという点かと思いますが、今の時代もはやそれ、どうでもいいんじゃないですかね

だって、コンストラクタの方にだけ引数足したらコンパイルエラーだし、しかも今の時代コンパイルせずともエディタがリアルタイムでエラーを指摘してくれるわけですし。補完も効くのでそうそうミスは起きません。

型のないpure javascriptだったらtypoの可能性があるので極力タイプ量を減らしたいというのはわかります。(他にも全フィールドに対してテスト書け、とか言われたりね)

しかし、IDE前提の現代のtypescriptでは変にループとreflection的なテクニックを駆使して汎化するよりもこれで十分じゃないの?と思ったりします。