TypeScript 类型推导真强大。 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
zhbhun
V2EX    TypeScript

TypeScript 类型推导真强大。

  •  2
     
  •   zhbhun 2024-10-18 14:18:06 +08:00 3809 次点击
    这是一个创建于 420 天前的主题,其中的信息可能已经有所发展或是发生改变。

    最近在学习开发客户端相关的功能,发现 Kotlin 和 Swift 要实现泛化的高阶函数不太容易。比如我要实现一个高阶函数,需要将传入的一个 async 函数转为串行执行的函数,必须等待前一个任务完成后才能开始下一个。使用 TS 可以这么做:

    function sequentialize<T xtends (...args: any[]) => Promise<any>>( asyncFn: T ): (...args: Parameters<T>) => ReturnType<T> { let queue: Promise<void> = Promise.resolve(); // 初始化队列 return function (...args: Parameters<T>): ReturnType<T> { const result = queue.then(() => asyncFn(...args)); // 将异步任务添加到队列中 queue = result.catch(() => {}); //捕获错误,防止队列中 return result as ReturnType<T>; //确保返回类型与原始函数一致 }; } async function plus(a: number, b: number): Promise<number> { await new Promise<void>((resolve) => { setTimeout(() => { resolve(); console.log(performance.now(), a, b); }, 1000); }); return a + b; } const sequentializePlus = sequentialize(plus); 

    但这在 Swift 和 Kotlin 里不太好处理,它们没法传入动态的函数,并包装后返回同类型的函数。想问下,如果像 Swift 和 Kotlin 这样的强类型语言要实现这样的语法,是否会存在什么限制?是否是因为 TS 编译后的 JS 是动态类型的,才支持这种类型推导(运行不会出问题),而 Swift 和 Kotlin 无法做到?

    13 条回复    2024-10-19 19:08:08 +08:00
    jy02534655
        1
    jy02534655  
       2024-10-18 14:23:55 +08:00
    这个应该和 TypeScript 关系不大吧,js 特性,js 是弱语言类型
    maichael
        2
    maichael  
       2024-10-18 14:27:01 +08:00
    JS 能这样实现,不是因为它强大,而恰恰是因为它够“弱”才能这么做;跟 Typescript 就更没啥直接关系了。
    zhbhun
        3
    zhbhun  
    OP
       2024-10-18 14:27:05 +08:00
    @jy02534655 是的,js 支持这种高阶函数的封装。但是 TS 加了类型后,也仍然支持,并且可以在编译时检查函数类型。所以有这个疑问,是否是因为像 JS 运行时支持这种写法才行,而 Swift 和 Kotlin 无法做到。
    wlingxiao
        4
    wlingxiao  
       2024-10-18 14:33:55 +08:00 via Android
    kotlin 了解的不多不确定能能不能做到,但是同为 jvm 上的语言 scala 可以做到,这些都是编译器的魔法,和运行时没关系。
    换个思路想,js 代码也是可以跑在 jvm 上的。
    hiwind
        5
    hiwind  
       2024-10-18 14:38:00 +08:00
    Kotlin 应该也能实现吧? https://book.kotlincn.net/text/lambdas.html
    类似于 Java 的 Functional Interface ?
    zhbhun
        6
    zhbhun  
    OP
       2024-10-18 14:45:16 +08:00
    @wlingxiao @dejavuwind 尝试用 Kotlin 写了下,没搞出来,让 ChatGPT 也说不行。主要是卡在 sequentialize 传入的函数无法是动的,没有像 TS 提供 Parameters 和 ReturnType 来推导传入的函数类型,只能固定参数类型和返回值,这样就违背了泛化的初衷
    hronro
        7
    hronro  
       2024-10-18 14:55:47 +08:00
    你这有点题不对文, [类型推导] 指的是不用写类型标注,编译器就能自动推导出变量的类型,TS 在这方面被 OCaml 秒成渣渣。
    至于你文中说的这种情况,只要是类型系统强大一点或者支持函数为一等公民的都能实现,和强弱类型没有任何关系,像 Rust 这种更偏底层的语言也能实现你之前提到的特性。
    zhbhun
        8
    zhbhun  
    OP
       2024-10-18 15:10:44 +08:00
    @hronro 感谢!我去学习下 OCaml 和 Rust 。标题确实没拟好,想改的发现改不了了。
    zhbhun
        9
    zhbhun  
    OP
       2024-10-18 16:24:13 +08:00
    @hronro 试了下 rust ,确实支持,看来还是跟语言设计有关系。

    ```rust
    fn with_logging<F, R>(args: F) -> R
    where
    F: FnOnce() -> R, // 接受一个闭包或函数,返回类型为 R
    {
    println!("执行函数之前的日志...");
    let result = args(); // 执行传入的闭包
    println!("执行函数之后的日志...");
    result // 返回传入闭包的返回值
    }

    fn main() {
    // 无参数函数
    let no_args_task = || {
    println!("无参数任务执行中...");
    42
    };

    // 单个参数函数
    let single_arg_task = |x: i32| -> i32 {
    println!("单个参数任务,参数为:{}", x);
    x * 2
    };

    // 多个参数函数,通过闭包包装来适配
    let multiple_args_task = |x: i32, y: i32| -> i32 {
    println!("多个参数任务,参数为:{}, {}", x, y);
    x + y
    };

    // 调用高阶函数
    let result1 = with_logging(no_args_task);
    let result2 = with_logging(|| single_arg_task(21));
    let result3 = with_logging(|| multiple_args_task(5, 10));

    println!("无参数任务返回值:{}", result1);
    println!("单个参数任务返回值:{}", result2);
    println!("多个参数任务返回值:{}", result3);

    // 最终输出
    // 执行函数之前的日志...
    // 无参数任务执行中...
    // 执行函数之后的日志...
    // 执行函数之前的日志...
    // 单个参数任务,参数为:21
    // 执行函数之后的日志...
    // 执行函数之前的日志...
    // 多个参数任务,参数为:5, 10
    // 执行函数之后的日志...
    // 无参数任务返回值:42
    // 单个参数任务返回值:42
    // 多个参数任务返回值:15
    ```
    hguandl
        10
    hguandl  
       2024-10-18 16:45:15 +08:00
    zhbhun
        11
    zhbhun  
    OP
       2024-10-18 20:27:45 +08:00
    @hguandl 真的可以耶,感谢大佬!
    zhbhun
        12
    zhbhun  
    OP
       2024-10-18 22:43:18 +08:00
    有哪位大佬知道 Kotlin 是否可以实现的吗?
    SoloCompany
        13
    SoloCompany  
       2024-10-19 19:08:08 +08:00
    有类型支持是好事
    但类型体操玩过头了就是给自己找不痛快
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     5106 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 28ms UTC 07:59 PVG 15:59 LAX 23:59 JFK 02:59
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86