📶

[connect-web]自作クラス内でPromiseClientの型定義

2023/12/02に公開

[connect-web]を使っている時に、自作クラス内のフィールドでPromiseClientを使うときのTypescriptの型定義に関するTipsです。

結論

PromiseClientのgenericsの中でtypeofで型を抽出する。

export class ChatServer {
    client: PromiseClient<typeof ChatService>

    constructor(url: string) {
        const transport = createConnectTransport({
            baseUrl: url
        })
        this.client = createPromiseClient(ChatService, transport)
    }
}

解説

createPromiseClientのgenericsの中身を見ると、こんな感じになってます。

const c: PromiseClient<{readonly typeName: "chat.v1.ChatService", readonly methods: {readonly connect: {readonly name: "Connect", read...

.protocからprotoc-gen-connect-esが自動生成したサービスは、constで定義されています。クラスではないのでそのままgenericsで渡せません。かといってPromiseClient<any>にしてしまうと…

export class ChatServer {
    clinet: PromiseClient<any>
    
    constructor(url string) {
        ...
    }
    async connect(name: string) {
        const res = await this.client.connect({
            name: "foo bar" // TS2353: Object literal may only specify known properties, and  name  does not exist in type
        })
    }
}

のように、Requestの型が失われてしまいエラーが発生してしまいます。

そのため、typeofを使ってServiceの型を抽出することでこの問題を解決できます。

client: PromiseClient<typeof ChatService>

tsに慣れてれば3秒ぐらいで解決しそうですが、慣れてないと困りそうなポイントなので念の為記事に…

Discussion