为何TypeScript函数返回值中的undefined未被类型检查器识别?
问题背景
在某共享数据库类库中,存在以下两个辅助函数声明:
/** Helper function to return *exactly* one result. */ export declare const one: <T>(a: T[]) => T; /** Helper function to return zero or one result. */ export declare const first: <T>(a: T[]) => T | undefined;
其中one函数类型检查正常,但first函数返回值联合类型中的undefined未被类型检查器识别,编译时直接被忽略;将返回值改为T | void后,代码中假设返回T的位置会触发预期的类型错误。该问题可在TypeScript Playground复现,但在项目中导入该模块时无错误提示。
可能的触发场景
strictNullChecks配置未启用
这是最常见的原因。当strictNullChecks设为false时,TypeScript会将undefined和null视为可赋值给任意类型的有效值,此时T | undefined会被等同于T,不会触发相关类型检查。noImplicitAny关闭导致类型推断异常
若noImplicitAny选项处于关闭状态,当TypeScript无法明确推断出泛型T的具体类型时,可能会将T推断为any,而any | undefined仍属于any类型,同样不会触发类型错误。非严格模式下的隐式赋值兼容
在非严格类型检查模式下,若调用first后直接将返回值赋值给声明为T类型的变量,编译器会默认忽略undefined的存在,认为该赋值是“安全”的。模块类型声明被覆盖或合并
项目中可能存在其他同名的first函数声明,或者该类库的类型声明被全局类型扩展、其他模块声明覆盖,导致实际生效的类型并非T | undefined。skipLibCheck选项启用
若项目开启了skipLibCheck,TypeScript会跳过对第三方依赖库的类型声明检查。如果该共享类库被当作第三方依赖引入,编译器不会验证其类型声明的正确性,自然不会发现undefined未被检查的问题。
内容的提问来源于stack exchange,提问作者Richard Coates

