TypeScript ts18047错误:filter函数中s可能为null的问题排查
Stream的filter函数TypeScript类型收窄异常
近期启用旧代码并添加TypeScript类型定义时,遇到了一个类型检查问题:在filter函数的闭包() => filter(s.next(), fn)处,TypeScript提示s可能为null,但此时代码处于while(s)分支内,s理应已被收窄为非null类型。类似逻辑的toArray函数能正常完成类型收窄,而通过const临时绑定s即可解决该错误。
Memo定义
type Memo<T> = () => T function memo<T>(fn: () => T): Memo<T> { let value: undefined | T = undefined return () => { if (value === undefined) value = fn() return value } }
Stream定义
type Stream<T> = null | { value: T next: () => Stream<T> } function stream<T>(value: T, next: () => Stream<T>): Stream<T> { return { value, next: memo(next), } }
报错的map和filter函数
function map<T, U>(s: Stream<T>, fn: (t: T) => U): Stream<U> { if (s) { return stream( fn(s.value), () => map(s.next(), fn), // ✅ s类型已收窄为非null,无报错 ) } return null } function filter<T>(s: Stream<T>, fn: (t: T) => boolean): Stream<T> { while (s) { if (fn(s.value)) { return stream( s.value, () => filter(s.next(), fn), // ❌ TypeScript提示:s可能为null ) } s = s.next() } return null }
类型收窄正常的toArray函数
function toArray<T>(s: Stream<T>): Array<T> { const r: Array<T> = [] while (s) { r.push(s.value) // ✅ s类型已收窄为非null,无报错 s = s.next() } return r }
解决方法
将当前非null的s绑定到一个const变量上,固定其类型,避免闭包引用时受后续重赋值的影响:
function filter<T>(s: Stream<T>, fn: (t: T) => boolean): Stream<T> { while (s) { if (fn(s.value)) { const m = s // ✅ 用常量保存当前非null的s return stream( m.value, () => filter(m.next(), fn), // ✅ m类型固定为非null,无报错 ) } s = s.next() } return null }
内容的提问来源于stack exchange,提问作者Mulan
相关产品推荐
相关产品推荐

