TypeScript Use any instead of unknown for AsyncGenerator optional .next parameter

1l5u6lss  于 9个月前  发布在  TypeScript
关注(0)|答案(1)|浏览(77)

TypeScript版本: 3.6.2
搜索词:

async generator, AsyncGenerator, optional .next

代码

以下代码会导致类型错误:

  1. async function* sequence(iterable: AsyncIterable<number>): AsyncGenerator<number> {
  2. yield 12;
  3. try {
  4. // Type error: Cannot delegate iteration to value because the 'next' method of its iterator expects type 'undefined', but the containing generator will always send 'unknown'.
  5. yield* iterable;
  6. } finally {
  7. console.log('Cleanup!');
  8. }
  9. }

预期行为:

我原本以为它不是一个类型错误。

问题:

这个问题的主要烦恼在于,我希望使用 AsyncGenerator<T> 只是为了指定 .return() 在早期清理时可以使用而不进行非空Assert(.return!()),但是 AsyncGenerator<T> 导致了 AsyncGenerator<T, any, unknown> ,所以 AsyncIterable<T> 不能委托给它。

建议解决方案:

interface AsyncGenerator<T = unknown, TReturn = any, TNext = unknown> 更改为 interface AsyncGenerator<T = unknown, TReturn = any, TNext = any
这不会破坏任何东西,因为 any 可以分配给任何东西,而且我不认为它会成为问题,因为使用 AsyncGenerator<T> (或 AsyncGenerator<T, S> )的人可能并不关心 .next 参数。

xtfmy6hx

xtfmy6hx1#

any 作为默认值的问题在于,它允许您使用 yield* 违反您正在委托给 yield* 的事物的 TNext 约束:

  1. async function * g(): AsyncGenerator<number, void, string> {
  2. const x = yield;
  3. x.toUpperCase(); // because `x` *must* be a string
  4. }
  5. async function * f(other: AsyncGenerator<number, void, string>): AsyncGenerator<number> {
  6. yield* other; // no error because `any` is assignable to `string`
  7. }
  8. // compile time: no error because `1` is assignable to `any`
  9. // runtime: errors because `toUpperCase` is not defined on a number
  10. f(g()).next(1);

也许 AsyncIteratorIterator 中的 TNext 的默认值应该是 unknown 而不是 undefined。我需要运行一些测试以验证这是否会产生其他副作用。

相关问题