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

如何让TypeScript函数必须返回联合类型的所有成员?

让TypeScript强制函数返回联合类型的所有成员

问题描述

我创建了一个响应对象及对应的工具类型,将其值转换为联合类型。我希望控制器返回该联合类型中的所有类型,但TypeScript仅返回其中一种类型时也会判定函数合法。如何让TypeScript仅在函数返回所有类型时才判定合法?

示例代码

// 模拟Zod库,示例中使用自定义方法
const z = {
    custom: function <T>() {
        return undefined as unknown as T
    },
}

type TestResponseType = {
    200: unknown,
    [status: number]: unknown
}

const response = {
    200: z.custom<object>(),
    404: z.custom<number>()
} satisfies TestResponseType

type TransformRoutes<T extends TestResponseType> = () => Promise<
    {[P in keyof T]: T[P]}[keyof T]
>

// 希望这个函数被判定为非法(仅返回number类型)
const shouldBeInvalid: TransformRoutes<typeof response> = async () => {
    return 1;
}

// 这个函数应该合法(返回了object和number所有类型)
const valid: TransformRoutes<typeof response> = async () => {
    if (Math.random() > 0.5) return {};
    else return 1;
}

解决方案

要实现这个需求,我们可以通过自定义条件类型,约束函数返回值必须穷尽联合类型的所有成员,未穷尽时直接触发类型错误。

修改后的代码如下:

// 模拟Zod库,示例中使用自定义方法
const z = {
    custom: function <T>() {
        return undefined as unknown as T
    },
}

type TestResponseType = {
    200: unknown,
    [status: number]: unknown
}

const response = {
    200: z.custom<object>(),
    404: z.custom<number>()
} satisfies TestResponseType

// 辅助类型:检查返回值是否覆盖联合类型的所有成员
type RequiresAllUnionMembers<Union, Return> = 
    Exclude<Union, Return> extends never ? Return : never;

// 重新定义TransformRoutes,加入成员覆盖检查
type TransformRoutes<T extends TestResponseType> = () => Promise<
    RequiresAllUnionMembers<{[P in keyof T]: T[P]}[keyof T], Awaited<ReturnType<TransformRoutes<T>>>>
>

// 触发类型错误:类型'Promise<number>'不能赋值给类型'Promise<never>'
const shouldBeInvalid: TransformRoutes<typeof response> = async () => {
    return 1;
}

// 正常通过类型检查
const valid: TransformRoutes<typeof response> = async () => {
    if (Math.random() > 0.5) return {};
    else return 1;
}

原理说明

  • RequiresAllUnionMembers<Union, Return> 的核心逻辑:使用Exclude<Union, Return>判断联合类型中是否存在未被返回值覆盖的成员。
    • 如果存在未覆盖的成员,Exclude<Union, Return>不会等于never,此时类型返回never,直接导致赋值错误。
    • 只有当返回值完全覆盖联合类型的所有成员时,Exclude<Union, Return>才会等于never,类型检查正常通过。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 21:35:01