如何通过TypeScript编译器强制处理非Void返回值的函数调用?
你当前用CanError<E>替代抛出错误的模式确实能避免难以排查的运行时错误,但遗漏处理返回值的风险确实存在。TypeScript编译器本身没有内置选项直接强制必须接收非void返回值的函数结果,但可以通过类型标记+ESLint规则的组合来实现你的需求,甚至能进一步强制处理错误路径。
方案1:用品牌类型标记需强制处理的返回值
先给你的CanError类型添加一个"品牌"标识,明确标记这是必须被处理的返回值:
// 定义品牌类型,用于标记必须处理的返回值 type MustHandle<T> = T & { __mustHandle: never }; // 包装原有的CanError类型 type CanError<E> = MustHandle<E | undefined>; function foo(): CanError<Error> { if (Math.random() > 0.5) { return new Error('did error') as CanError<Error>; } return undefined as CanError<Error>; }
这个标记能让后续的ESLint规则精准识别需要强制处理的函数返回值。
方案2:ESLint规则强制处理返回值
使用@typescript-eslint/no-unused-expressions规则,配合不同配置实现不同程度的强制:
基础配置(针对所有非void返回值)
如果可以接受对所有非void返回值的函数生效,直接在ESLint配置中开启:
{ "parser": "@typescript-eslint/parser", "plugins": ["@typescript-eslint"], "rules": { "@typescript-eslint/no-unused-expressions": [ "error", { "allowShortCircuit": false, "allowTernary": false, "allowVoid": true } ] } }
这个配置会禁止任何非void返回值的函数被直接调用(除非用void foo()主动忽略),但可能会影响其他无需强制处理返回值的函数。
精准配置(仅针对CanError类型)
如果只想针对返回CanError的函数,可以编写自定义ESLint规则,利用TypeScript的类型检查能力判断函数调用的返回值是否为CanError类型:通过@typescript-eslint/type-utils获取函数返回值的类型信息,检查是否包含__mustHandle品牌标识,若是且未被赋值或使用则报错。
方案3:结合--noUnusedLocals强制处理返回值
开启TypeScript的--noUnusedLocals编译选项,配合前面的规则:当你必须接收CanError类型的返回值后,若未使用该变量(即未处理错误路径),编译器会直接报错。这能进一步确保你不会接收了返回值却不处理。
总结
最贴合你需求的方案是:
- 用品牌类型标记
CanError,明确需强制处理的返回值; - 配置ESLint规则禁止直接调用这类函数而不接收结果;
- 开启
--noUnusedLocals确保接收返回值后必须处理。
这套组合既能识别完全未处理错误路径的位置,又能避免误影响其他函数。
内容的提问来源于stack exchange,提问作者TrevTheDev

