如何处理带有互斥参数的TypeScript函数?
问题描述
我希望addNumbers函数始终返回数字,将b或c与a相加。参数a为必填项,b和c同样为必填项,但二者互斥,即不能同时传入。
我尝试了以下写法:
function addNumbers1({ a, b, c, }: { a: number } & ( | { b: number; c?: never } | { c: number; b?: never } )): // 此处TypeScript报错:"Function lacks ending return statement and return type does not include 'undefined'.(2366)" number { if (b) { return a + b; } if (c) { return a + c; } }
出现上述Function lacks ending return statement and return type does not include 'undefined'.(2366)错误后,我尝试添加校验确保b或c始终被定义,避免无返回值的情况:
function addNumbers2({ a, b, c, }: { a: number } & ( | { b: number; c?: never } | { c: number; b?: never } )): number | string { // 添加该行代码防止b或c为undefined if (b === undefined && c === undefined) return "error"; // 此时b或c必然已定义,以下条件之一应始终返回数字 // 但TypeScript仍报错:Function lacks ending return statement and return type does not include 'undefined'.(2366) if (b) { return a + b; } if (c) { return a + c; } }
我又尝试了另一种写法:
function addNumbers3({ a, b, c, }: { a: number } & ( | { b: number; c?: never } | { c: number; b?: never } )): number | string { // 再次确保b或c其中一个已定义 if (b === undefined && c === undefined) return "error"; if (b) { return a + b; } else { // 但此时报错:"'c' is possibly 'undefined'.(18048)" // 明明已经做了校验,为什么会这样? return a + c; } }
请问处理该问题的最佳方案是什么?我希望保留当前的函数参数结构。
编辑说明:如果将示例中的number类型改为string类型,示例会更合理——检查数字0的真值时存在另一个问题。
解决方案
问题核心有两点:一是TypeScript无法自动通过联合类型的结构完成精准类型收窄,二是用if (b)这种真值判断会漏掉b=0的合法情况。以下是适配你需求的最优方案:
方案一:严格存在性判断+运行时兜底
完全保留你原有的参数结构,通过严格的存在性判断替代真值判断,同时添加运行时兜底避免非法调用:
function addNumbers({ a, b, c, }: { a: number } & ( | { b: number; c?: never } | { c: number; b?: never } )): number { // 运行时兜底:防止非TS环境调用或类型绕过 if (b === undefined && c === undefined) { throw new Error("必须传入b或c中的一个"); } // 用严格存在性判断替代真值判断,避免漏掉b=0的情况 if (b !== undefined) { return a + b; } // 此时TypeScript能通过联合类型推断出c必然存在,无需额外断言 return a + c; }
为什么这个方案可行?
- 用
b !== undefined替代if (b),解决了数字0被误判为“不存在”的问题; - 兜底判断抛出错误而非返回字符串,保证函数始终返回数字,符合你最初的需求;
- 当排除
b存在的情况后,TypeScript能根据联合类型的约束,自动推断出c必然存在,不会再报undefined错误。
为什么之前的写法会报错?
- addNumbers1报错:
if (b)是真值判断,会漏掉b=0的合法情况,导致代码可能走到函数末尾无返回值,TypeScript因此报错; - addNumbers2报错:同样的真值判断问题,当
b=0或c=0时,两个if分支都不会触发,函数依然可能无返回值; - addNumbers3报错:
if (b)的真值判断无法让TypeScript区分“b=0”和“b不存在”两种情况,所以进入else分支后,TypeScript依然认为c可能是undefined。
内容的提问来源于stack exchange,提问作者Björn
相关产品推荐
相关产品推荐

