如何让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
相关产品推荐
相关产品推荐

