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

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

TypeScript版本: 3.6.2
搜索词:

async generator, AsyncGenerator, optional .next

代码

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

async function* sequence(iterable: AsyncIterable<number>): AsyncGenerator<number> {
  yield 12;
  try {
    // 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'.
    yield* iterable;
  } finally {
    console.log('Cleanup!');
  }
}

预期行为:

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

问题:

这个问题的主要烦恼在于,我希望使用 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 约束:

async function * g(): AsyncGenerator<number, void, string> {
  const x = yield;
  x.toUpperCase(); // because `x` *must* be a string
}

async function * f(other: AsyncGenerator<number, void, string>): AsyncGenerator<number> {
  yield* other; // no error because `any` is assignable to `string`
}

// compile time: no error because `1` is assignable to `any`
// runtime: errors because `toUpperCase` is not defined on a number
f(g()).next(1);

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

相关问题