⏭️

Typescriptでもデリゲートがしたい!

2024/02/13に公開

というわけで、ライブラリを作りました。

https://github.com/tkow/ts-delegate

import { delegate, delegateProxy } from '@tkow/ts-delegate'

interface IChild {
  hello: (name: string) => string
  goodbye: () => string
}

class Child implements IChild {
  hello(name: string) {
    return `Hello, ${name}`
  }
  goodbye() {
    return 'Goodbye'
  }
}

class Parent {
  constructor() {
    delegateProxy(this, new Child())
  }
  hello = delegate<Child, 'hello'>('hello')
  goodbye = delegate<Child, 'goodbye'>('goodbye')
}

console.log(new Parent().hello('World')) // 'Hello, World'
console.log(new Parent().goodbye()) // 'Goodbye'

delegateProxyメソッドで、インスタンス内にproxyを保持する内部変数を保持し、delegateメソッドで内部proxyを使ったメソッド呼び出しをparentクラスにマッピングする事で実現しました。

型引数を用いることで、delegate先のメソッドの型を引き継ぐことが出来ます。

delegateされるメソッドが確定されるまで、delegateProxyの呼び出しはdelegate実行よりも遅延できます。これにより先にinterfaceを型パラメータとしてdelegateを実行した状態で、実装の実態が未定義のままでもdelegateProxyを呼び出すタイミングで、処理を変更できるという面白い使い方もできます。

なんでデリゲートしたいの?

実装を親に引き継ぐことで、必要なメソッドの再実装を防げます。インターフェースを踏襲したインスタンスを置き換えることで、クラス内で利用される実装の差し替えも簡単になります。

終わりに

Proxy class以外に依存関係もなく軽いライブラリなのでtypescriptでもデリゲートしたくなった方はぜひ使ってみてください。

Discussion