如何在 Typescript 中检查 http 调用的返回类型?

问题描述 投票:0回答:1

问题:

不确定这是否重要,但我正在处理 Firebase 云功能。

假设我有以下功能:

function giveMeAnInteger(): number {
    return 123;
}

我用以下方式调用该函数:

function call() {
    const result = giveMeAnInteger();
    console.log(result.split(" "));
}

Typescript 可以静态检查返回类型,并抱怨“类型‘number’上不存在属性‘split’。”
现在假设我有一个类似的函数,已发布到 firebase 的云函数

export const giveMeAnInteger = functions.https.onCall((): number => {
    return 123;
});

当我调用云函数时,Typescript 无法推断响应的类型,这可能会导致潜在的运行时错误:

const giveMeAnInteger = httpsCallable(functions, "giveMeAnInteger");

export function test() {
    giveMeAnInteger().then((result) => {
        const res = result.data
        console.log(res.split(" "));
    });
}

我收到错误“‘res’的类型为‘未知’。”因为这是 httpsCallable 的类型签名:

HttpsCallable<unknown, unknown>

尝试1:

首先,我可以在函数调用本身之前声明类型:

const giveMeAnInteger = httpsCallable<void, number>(functions, "giveMeAnInteger");

export function test() {
    giveMeAnInteger().then((result) => {
        const res = result.data
        console.log(res.split(" "));
    });
}

如果我这样做,打字稿现在会给出正确的投诉。然而,这抵消了 TypeScript 的好处,因为它现在依赖于客户端的用户来“设置”函数的返回类型,它还要求客户端了解云函数的实现细节。如果我错误地将返回类型设置为字符串:

const giveMeAnInteger = httpsCallable<void, string>(functions, "giveMeAnInteger");

export function test() {
    giveMeAnInteger().then((result) => {
        const res = result.data
        console.log(res.split(" "));
    });
}

Typescript 不会抱怨,但会出现运行时错误,因为该函数返回整数而不是字符串。
我希望能够告诉打字稿“如果这个http调用成功,这就是将要返回的类型”。并且应该在编译时捕获类型错误。

尝试2:

我可以“硬编码”云函数的返回类型并将其导出:

export const giveMeAnInteger = functions.https.onCall((): number => {
    return 123;
});

export type ReturnTypeOfGiveMeAnInteger = number;

然后我可以在函数调用之前导入它并执行如下操作:

import { ReturnTypeOfGiveMeAnInteger } from ...

export function test() {
    giveMeAnInteger().then((result) => {
        const res = result.data as ReturnTypeOfGiveMeAnInteger
        console.log(res.split(" "));
    });
}

现在静态检查是正确的,我可以将云函数视为黑匣子而不知道其实现。由于我在创建函数的位置声明了类型,因此人为错误的可能性也降低了。然而,这个解决方案并不适合我,因为它感觉太老套,或者“硬编码”。

我希望能够在 http 调用成功时获取其类型。我想以一种非黑客的方式做到这一点。客户端不应该知道云功能的实现细节。 您还有其他我可以尝试的潜在解决方案吗?我很乐意根据要求分享更多详细信息。

typescript firebase types google-cloud-functions
1个回答
0
投票

TypeScript 无法从调用者的角度静态推断可调用函数的返回类型。就 TypeScript 编译器而言,客户端和服务器代码彼此完全无关,因为它不了解 Firebase SDK 如何序列化和反序列化返回数据(在此过程中任何事情都可能发生) - 编译器无法确定)。因此,所有可调用函数都会返回

unknown
,并且您必须将其转换为所需的类型,就像现在一样。没有任何解决方法可以使纯 TypeScript 实现变得更容易。

如果您希望对返回类型的结构和内容有更多保证,请使用运行时类型模式(例如 zod)来验证返回数据是否与您期望后端发送的数据匹配。

© www.soinside.com 2019 - 2024. All rights reserved.