TypeScript中如何实现支持null入参的带类型收窄自定义谓词函数?
TypeScript 谓词函数类型缩窄避坑方案
你遇到的问题本质是类型谓词的范围定义太宽泛,导致TS在else分支做了过度缩窄,可通过以下几种方案解决:
- 方案1:使用精准子类型谓词
如果你的Shape是可辨识联合类型,直接将类型谓词指定为Blobby对应的子类型即可,同时会自动排除null场景:
type Shape = Blobby | Rect | Circle interface Blobby { type: 'blobby' color: string blobRadius: number } interface Rect { type: 'rect' width: number height: number } interface Circle { type: 'circle' radius: number } function isBlobby(s: Shape | null): s is Blobby { return s?.type === 'blobby' } // 调用示例 const x: Shape | null = getShape() if (isBlobby(x)) { doSomethingWith(x.color) // 无需非空断言 } else { // 此处x类型为 Rect | Circle | null,不会被错误缩窄为null }
- 方案2:为非联合类型构造交叉类型谓词
如果Shape是普通接口,没有定义可辨识联合,可以直接在类型谓词中声明Blobby形态需要满足的属性约束:
interface Shape { type?: string color?: string radius?: number } function isBlobby(s: Shape | null): s is Shape & { type: 'blobby', color: string } { return s != null && s.type === 'blobby' && typeof s.color === 'string' }
该方案的使用效果和可辨识联合方案完全一致,else分支不会出现过度缩窄问题。
- 方案3:不修改谓词的轻量适配写法
如果你不想调整原有isBlobby的返回类型定义,可以在判断时额外加一层非空校验,TS会自动完成类型缩窄:
// 保持原有谓词定义不变 function isBlobby(s: Shape | null): boolean { return s != null && s.type === 'blobby' } const x: Shape | null = getShape() if (x && isBlobby(x)) { doSomethingWith(x.color) // 无需非空断言 } else { // x类型仍保持为 Shape | null }
内容的提问来源于stack exchange,提问作者Tom Locke
相关产品推荐
相关产品推荐

