TypeScript中使用null作为判别式的联合类型失效问题求助
解决TypeScript中null作为联合类型判别式的类型推断问题
你遇到的问题核心是:解构后独立变量的类型关联无法被TypeScript正确跟踪。虽然TypeScript支持null作为判别式,但这种支持是针对对象属性的直接检查,而非解构后的孤立变量——当你把error和result拆成单独变量后,TypeScript没法再关联二者的类型互斥关系。
以下是几个实用的解决方法:
方法1:避免提前解构,直接检查返回对象的属性
不需要修改原Result类型定义,直接对返回的完整对象做类型窄化:
const registerResult = await register(fields); if (registerResult.error) { return typedjson({ fields, fieldErrors: { email: registerResult.error } }); } // 此处TypeScript能正确推断registerResult.result为T类型 const user = registerResult.result; // 后续正常使用user即可
这种方式完全利用TypeScript对联合类型的原生窄化能力,类型推断精准且无冗余代码。
方法2:优化联合类型结构(更简洁的布尔判别式)
如果愿意调整Result类型,可以去掉冗余的null属性,改用布尔值作为明确判别式,同时保持代码简洁:
type Result<T> = { success: true; result: T } | { success: false; error: string };
使用时解构只需要关注必要的变量,逻辑更清晰:
const { success, error, result: user } = await register(fields); if (!success) { return typedjson({ fields, fieldErrors: { email: error } }); } // 此处user自动推断为T类型
相比你之前的临时方案,这个结构去掉了不必要的result: null和error: null,语义更直观。
方法3:使用类型守卫函数(进阶方案)
如果需要频繁处理这类Result类型,可以定义一个类型守卫函数来手动窄化类型:
type Result<T> = { result: T; error: null } | { result: null; error: string }; function isSuccess<T>(res: Result<T>): res is { result: T; error: null } { return res.error === null; }
使用时结合守卫函数:
const registerResult = await register(fields); if (!isSuccess(registerResult)) { return typedjson({ fields, fieldErrors: { email: registerResult.error } }); } const user = registerResult.result;
这种方式适合在大型项目中统一处理这类结果类型,保持代码风格一致。
内容的提问来源于stack exchange,提问作者André Casal
相关产品推荐
相关产品推荐

