最初にやろうとしたこと
interfaceでstaticプロパティを宣言して、その実装クラスで初期化しようとしました。
interface MoneyIF { static readonly CurrencyUnit: string readonly amount: number } class JPY implements MoneyIF { static readonly CurrencyUnit: string = 'Yen' readonly amount: number constructor(amount: number) { this.amount = amount } } class USD implements MoneyIF { static readonly CurrencyUnit: string = 'Dollar' readonly amount: number constructor(amount: number) { this.amount = amount } }
が、残念ながらinterfaceで次の表示が、、
// static' modifier cannot appear on a type member.
oh...
abstract classで表現してみる
を中心に議論されていますが、現在のバージョンでは、interfaceでstaticプロパティ、メソッドは定義できません。
まだ結論は出ていないようですが、abstract classで宣言する人たちが一定数いることがわかり、手軽に実装できそうでもあったのでその方針で実装してみました。
abstract class MoneyBase { static readonly CurrencyUnit: string readonly amount: number protected constructor(amount: number) { this.amount = amount } } class JPY extends MoneyBase { static readonly CurrencyUnit: string = 'Yen' constructor(amount: number) { super(amount) } } class USD extends MoneyBase { static readonly CurrencyUnit: string = 'Dollar' constructor(amount: number) { super(amount) } } const usd: MoneyBase = new USD(100) console.log(usd.amount) // 100 console.log(USD.CurrencyUnit) // "Dollar"
いい感じに扱えそうです。
ただここで新たな問題が、、
console.log(usd.CurrencyUnit) // Property 'CurrencyUnit' does not exist on type 'MoneyBase'. Did you mean to access the static member 'MoneyBase.CurrencyUnit' instead?
インスタンス経由ではstaticプロパティにアクセスできないのです。。
インスタンス経由でstaticプロパティにアクセスする
ちょっと調べてみたところ、いい感じの方法がありました。
this.constructor
経由でstaticプロパティを呼び出す関数を実装しておく方法です。
実装はこんな感じになります。
abstract class MoneyBase { static readonly CurrencyUnit: string readonly amount: number protected constructor(amount: number) { this.amount = amount } get CurrencyUnit() { return (this.constructor as typeof MoneyBase).CurrencyUnit } } class JPY extends MoneyBase { static readonly CurrencyUnit: string = 'Yen' constructor(amount: number) { super(amount) } } class USD extends MoneyBase { static readonly CurrencyUnit: string = 'Dollar' constructor(amount: number) { super(amount) } } const usd: MoneyBase = new USD(100) console.log(usd.CurrencyUnit) // "Dollar" console.log(USD.CurrencyUnit) // "Dollar"
インスタンス経由からも、クラスからも無事staticプロパティを呼び出すことに成功しました!
おわりに
議論の余地はありそうではありますが、とりあえずは実装できました。
こうやったらもっと良いよ!とかあれば、教えていただけると嬉しいです!