求助 TypeScript 中关于 Generator 的类型定义

2022-04-09 23:05:45 +08:00
 johnkiller
const sum = (a: number, b: number) => a + b

const toUpper = (s: string) => s.toUpperCase()

function* main() {
  const a = yield sum(1, 5)
  console.log(a)

  const b = yield toUpper('Hello')
  console.log(b)
}

此时ab的类型为any
现在想让生成器函数 main 中的ab能够自动推导出numberstring
也就是 yield 的返回值,一定是 yield 后面的「函数」的返回值类型(函数已经执行了,或者说后面的值类型)。

不胜感激🙏

1152 次点击
所在节点    问与答
7 条回复
johnkiller
2022-04-09 23:21:29 +08:00
动机是因为我已经通过 generator+promise 实现了 async await ,但是卡在了写类型约束这里。
比如下面原生的 async await 版本,是能够推导出 a ,b 的类型的:

```ts

async function main() {
const a = await sum(1, 2)
console.log(a)

const b = await toUpper('Hello')
console.log(b)
}

```
yor1g
2022-04-09 23:48:24 +08:00
不是自动推导出了 function* main(): Generator<string | number, void>??
mxT52CRuqR6o5
2022-04-10 00:13:29 +08:00
yield 的返回值推导不出来的,你问出这个问题说明你对 generator 的理解不深或是有错误的理解
mxT52CRuqR6o5
2022-04-10 00:16:44 +08:00
@johnkiller
你用 generator+promise 实现 async await 是实现了一种特殊的 generator 执行器( typescript 是不可能知道的),会把 promise 的结果扔回给 generator 作为 yield 的返回值,但实际上 yield 是可以可能返回任何东西的
johnkiller
2022-04-10 13:09:17 +08:00
@mxT52CRuqR6o5 感谢回复

我并不是说要 ts 去自动推导,因为它根本就没有找到 next()会传入什么类型的线索。
我是想通过显示的声明,告诉它 a/b 的类型取决于后者,毕竟 ts 泛型还是有一定的灵活性的。

因为以下的例子可以通过 Generator 的第 3 个参数明确告知 yield 类型,所以我才会想有没有一种泛型的实现方式。

https://reurl.cc/ZrD3gM


当然严格按照我以上的要求是无法实现的,不过我有以下 3 个替代方案:

https://reurl.cc/Opd3ey
https://reurl.cc/RjAGQx
https://reurl.cc/zM0R4y
mxT52CRuqR6o5
2022-04-10 19:29:47 +08:00
@johnkiller
Generator 的第 3 个参数是标记的所有的 yield 的返回值,所以应该是没有能力通过它来实现类型自动标注的
只能是通过 yield*去实现,因为 yield*可以推导出返回值类型
mxT52CRuqR6o5
2023-06-08 16:10:12 +08:00
https://mobx-keystone.js.org/data-models#flows-async-actions
可以看看这个 case
通过实现一个_await 来把 Promise<T>类型转换成 Generator<T>,从而可以使用 yield*来获取到返回值类型
可以用类似的思路做 yield 类型标注

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/845961

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX