You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让TypeScript自动推断泛型Result包裹的函数返回类型?

让TypeScript自动推断Result泛型的区分联合类型,无需手动定义T类型

问题分析

你定义了泛型Result类型用于封装操作结果,但类方法中直接返回对象字面量时,TypeScript会将返回类型推断为非区分联合类型({ ok: boolean; value?: T; error?: E }),而非预期的Result<T, E>区分联合。这会导致类型守卫失效——比如判断!result.ok后,TS仍提示result.error可能为undefined。手动指定返回类型又需要维护额外的MyDataType,无法自动同步数据库查询的类型变化。

解决方案:使用辅助函数约束返回类型

通过创建两个简单的辅助函数ok和err,明确返回Result类型的字面量联合,让TypeScript自动推断泛型参数T和E,同时保证返回类型是区分联合类型,类型守卫可以正常工作。

完整代码示例

export type Result<T, E = Error> =
    | { ok: true; value: T }
    | { ok: false; error: E };

// 辅助函数:封装成功结果,自动推断T类型
const ok = <T>(value: T): Result<T> => ({ ok: true, value });

// 辅助函数:封装错误结果,自动推断E类型(默认Error)
const err = <E = Error>(error: E): Result<never, E> => ({ ok: false, error });

class DataRepository {
    async getSomeData() {
        const data = await Promise.resolve(
            Math.random() < 0.5 ? null : { something: 42 }
        );

        if (!data) {
            return err(new Error("Invalid ..."));
        }

        return ok(data);
    }
}

async function example() {
    const repo = new DataRepository();
    const result = await repo.getSomeData();

    if (!result.ok) throw result.error; // 类型守卫正常工作,无undefined提示
    const something = result.value.something; // 正确识别value的类型,无undefined提示
}

原理说明

  • 辅助函数ok和err明确返回Result<T>和Result<never, E>类型,其中ok属性是字面量类型true/false,而非宽泛的boolean。
  • TypeScript会自动从传入的value和error参数推断出泛型T和E的具体类型,无需手动定义。
  • 最终方法的返回类型会被推断为Promise<Result<{ something: number }, Error>>,属于标准的区分联合类型,类型守卫可以正确缩小类型范围。

替代方案:显式注解返回类型(无需手动定义T)

如果不想使用辅助函数,也可以直接给方法添加返回类型注解,利用TypeScript的类型推断自动填充泛型参数:

class DataRepository {
    async getSomeData(): Promise<Result<Awaited<ReturnType<typeof this.prisma.dataset.findMany>>>> {
        const data = await this.prisma.dataset.findMany({ ... });
        
        if (!data) {
            return { ok: false, error: new Error("Invalid ...") };
        }

        return { ok: true, value: data };
    }
}

这种方式通过ReturnType<typeof ...>获取数据库查询方法的返回类型,再用Awaited处理异步类型,无需手动定义MyDataType,但写法比辅助函数繁琐。

内容的提问来源于stack exchange,提问作者Haardik

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 14:33:39