Swiftに慣れるとどうしても Generics でclassの定義をしたくなりませんか?
Firebase Cloud Functionsを初めてからとことんTypeScriptを書くことが多くなってきたのでちょっとしたTipsを紹介します。

この文章はあくまでもSwiftに慣れた人がTypeScriptを書く場合のコツです。TypeScript本家の方でもっといい方法を知っている方がいればぜひご教示下さい。

ProtocolとInterface

SwiftのProtocolに相当するTypeScriptの構文はInterfaceです。
TypescriptのInterfaceはSwiftのProtocol Extensionができないなど物足りなさも感じますが、Classに必要なプロパティやファンクションを定義する意味では充分に機能します。

protocol AProtocol {

}
interface AProtocol {

}

ここまでは非常に似ているが。。

Genericsをつけると途端にわかりにくい

さぁこれにGenericsを加えていきましょう。

Swift

protocol AProtocol {
    init()
}

protocol BProtocol {
    associatedtype A: AProtocol
}

class Fuga: AProtocol {
    required init() {}
}

class Hoge<T: AProtocol>: BProtocol {
    typealias A = T
    func fuga() -> A {
        let a: A = A()
        return a
    }
}

let hoge: Hoge<Fuga> = Hoge()
let a: Fuga = hoge.fuga()

TypeScript

interface AProtocol {

}

interface BProtocol<A extends AProtocol> {

}

class Fuga implements AProtocol {

}

class Hoge <A extends AProtocol> implements BProtocol<A> {

    private _A: { new(): A }

    fuga(): A {
        const a: A = new this._A()
        return a
    }
}

const hoge: Hoge<Fuga> = new Hoge()
const a: Fuga = hoge.fuga()

考え方を整理するポイントは2つ

  • associatedtype
  • { new(): A }

TypeScriptでassociatedtypeっぽいことをする

Swiftのassociatedtypeは、TypeScriptでは BProtocol<A extends AProtocol>のように依存するプロトコルを宣言します。

Genericsの型を初期化

TypeScriptでGenericsの型を初期化するには{ new(): A }が必要です。Swiftのassociatedtypeの代わりに

private _A: { new(): A }

を宣言しています。こうすることでclass内ではどこでもAを初期化することが可能になります。

Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account log in.