V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
johnkiller
V2EX  ›  问与答

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

  •  
  •   johnkiller · 2022-04-09 23:05:45 +08:00 · 1143 次点击
    这是一个创建于 969 天前的主题,其中的信息可能已经有所发展或是发生改变。
    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 后面的「函数」的返回值类型(函数已经执行了,或者说后面的值类型)。

    不胜感激🙏

    7 条回复    2023-06-08 16:10:12 +08:00
    johnkiller
        1
    johnkiller  
    OP
       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
        2
    yor1g  
       2022-04-09 23:48:24 +08:00
    不是自动推导出了 function* main(): Generator<string | number, void>??
    mxT52CRuqR6o5
        3
    mxT52CRuqR6o5  
       2022-04-10 00:13:29 +08:00
    yield 的返回值推导不出来的,你问出这个问题说明你对 generator 的理解不深或是有错误的理解
    mxT52CRuqR6o5
        4
    mxT52CRuqR6o5  
       2022-04-10 00:16:44 +08:00
    @johnkiller
    你用 generator+promise 实现 async await 是实现了一种特殊的 generator 执行器( typescript 是不可能知道的),会把 promise 的结果扔回给 generator 作为 yield 的返回值,但实际上 yield 是可以可能返回任何东西的
    johnkiller
        5
    johnkiller  
    OP
       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
        6
    mxT52CRuqR6o5  
       2022-04-10 19:29:47 +08:00
    @johnkiller
    Generator 的第 3 个参数是标记的所有的 yield 的返回值,所以应该是没有能力通过它来实现类型自动标注的
    只能是通过 yield*去实现,因为 yield*可以推导出返回值类型
    mxT52CRuqR6o5
        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 类型标注
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3327 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 12:11 · PVG 20:11 · LAX 04:11 · JFK 07:11
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.