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)
}
此时a
和b
的类型为any
,
现在想让生成器函数 main 中的a
和b
能够自动推导出number
和string
,
也就是 yield 的返回值,一定是 yield 后面的「函数」的返回值类型(函数已经执行了,或者说后面的值类型)。
不胜感激🙏
1
johnkiller OP 动机是因为我已经通过 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) } ``` |
2
yor1g 2022-04-09 23:48:24 +08:00
不是自动推导出了 function* main(): Generator<string | number, void>??
|
3
mxT52CRuqR6o5 2022-04-10 00:13:29 +08:00
yield 的返回值推导不出来的,你问出这个问题说明你对 generator 的理解不深或是有错误的理解
|
4
mxT52CRuqR6o5 2022-04-10 00:16:44 +08:00
@johnkiller
你用 generator+promise 实现 async await 是实现了一种特殊的 generator 执行器( typescript 是不可能知道的),会把 promise 的结果扔回给 generator 作为 yield 的返回值,但实际上 yield 是可以可能返回任何东西的 |
5
johnkiller OP @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 |
6
mxT52CRuqR6o5 2022-04-10 19:29:47 +08:00
@johnkiller
Generator 的第 3 个参数是标记的所有的 yield 的返回值,所以应该是没有能力通过它来实现类型自动标注的 只能是通过 yield*去实现,因为 yield*可以推导出返回值类型 |
7
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 类型标注 |