如何为Generator生成器函数应用函数类型定义?
异步生成器函数的类型定义问题
我有一个异步生成器函数:
async function * filterIterable (iter, predicate) { let i = 0 for await (const val of iter) { if (predicate(val, i++)) { yield val } } }
希望为以下两种使用场景添加类型定义:
// 类型谓词函数 const nonNullable = <T>(val: T | undefined | null): val is T => val !== undefined && val !== null async function * gen1 () { yield 1 yield 2 yield 3 } async function * gen2 () { yield 1 yield undefined yield 3 } const it1 = filterIterable(gen1(), n => n % 2 === 0) const it2 = filterIterable(gen2(), nonNullable) // 期望类型为 AsyncIterable<1 | 3>
我编写了如下接口,它可以应用于函数表达式,但相关文档说明无法直接应用于函数声明:
interface FilterIterable { <T> ( iter: AsyncIterable<T>, predicate: (val: T, index: number) => boolean, ): AsyncIterable<T>; <T, S extends T> ( iter: AsyncIterable<T>, predicate: (val: T, index: number) => val is S, ): AsyncIterable<S>; }
请问异步生成器函数是否也无法直接应用这类接口类型?
结论
是的,异步生成器函数声明同样无法直接应用你定义的FilterIterable接口类型。TypeScript中,函数声明(包括生成器、异步生成器函数)不支持直接绑定接口类型,只能通过直接为函数声明添加泛型与重载注解来实现相同的类型约束效果。
解决方法
直接修改filterIterable的函数声明,将泛型逻辑通过函数重载实现:
// 重载签名1:普通断言函数 async function* filterIterable<T>( iter: AsyncIterable<T>, predicate: (val: T, index: number) => boolean ): AsyncIterable<T>; // 重载签名2:类型谓词函数 async function* filterIterable<T, S extends T>( iter: AsyncIterable<T>, predicate: (val: T, index: number) => val is S ): AsyncIterable<S>; // 函数实现体 async function* filterIterable<T, S extends T>( iter: AsyncIterable<T>, predicate: (val: T, index: number) => boolean ) { let i = 0; for await (const val of iter) { if (predicate(val, i++)) { yield val; } } }
这样修改后,两种使用场景都能获得正确的类型推导:
it1会被推导为AsyncIterable<number>it2会被推导为AsyncIterable<1 | 3>
原理说明
这种写法利用了TypeScript的函数重载特性,将你原本在接口中定义的两个泛型签名,直接作为生成器函数的重载签名,配合实现体的类型兼容,就能达到和用接口约束函数表达式完全一致的类型效果。
内容的提问来源于stack exchange,提问作者mb21
相关产品推荐
相关产品推荐

