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

关于 typescript 里的泛型(Generics),不太理解为什么要这么繁琐?

  •  
  •   find456789 · 2020-05-28 14:53:24 +08:00 · 2770 次点击
    这是一个创建于 1645 天前的主题,其中的信息可能已经有所发展或是发生改变。

    比如这一段代码:

    function identity<T>(arg: T): T {
        return arg;
    }
    

    为什么不写成这样呢?删掉 <T> 不是看上去更简单吗

    function identity(arg: T): T {
        return arg;
    }
    
    第 1 条附言  ·  2020-05-28 16:08:27 +08:00
    冒昧再请教一下

    问题 1: 如果我不加<T>, 编译器 有可能以为 T 是一个自定义的 interface 或者 type 对吗?

    问题 2: 如果我加了 <T>, 就是 先告诉编译器,接下来的 T 是个泛型,而不是自定义 interfa 、type, 对吗
    16 条回复    2020-05-29 15:30:16 +08:00
    abbycin
        1
    abbycin  
       2020-05-28 15:22:14 +08:00 via Android
    你要写 cpp 还会看到 template<typename T> auto identify (T arg) -> T { return arg ; }
    hua123s
        2
    hua123s  
       2020-05-28 15:48:07 +08:00
    type T = {
    我还用不用了
    }
    Aynamic
        3
    Aynamic  
       2020-05-28 15:52:25 +08:00 via Android   ❤️ 1
    图一你可以理解为 T 是一个未确定的类型,调用方法时候可以指明 T 的类型,图二 T 是一个已知的类型。
    wysnylc
        4
    wysnylc  
       2020-05-28 15:53:24 +08:00
    也让你们体会下 Java 泛型带来的恐惧嘎嘎嘎
    BingoXuan
        5
    BingoXuan  
       2020-05-28 15:53:38 +08:00 via Android
    <>是声明泛型用的吧,例如<T,S>就声明泛型 T 和 S 可以用。

    我觉得 Python 的泛型声明才是最恶心的
    eGlhb2Jhb2Jhbw
        6
    eGlhb2Jhb2Jhbw  
       2020-05-28 15:59:17 +08:00   ❤️ 1
    你觉得编译器怎么知道你是想用泛型还是手残敲出了个未定义的类型?
    jswh
        7
    jswh  
       2020-05-28 16:01:31 +08:00
    <T>里的 T 是声明,声明了之后后面才可以用鸭。
    cxe2v
        8
    cxe2v  
       2020-05-28 16:07:36 +08:00   ❤️ 1
    微软的泛型最早出现在.NET 里面,.NET 泛型的定义里有个类型参数,类型参数就是用来给实际类型使用时候的占位符,创建泛型类的时候,需要将 T 替换成实际类型,例如
    ```c#
    public class identity{
    public T A<T>(T arg){
    return arg;
    }
    }

    identity I=new identity();
    I.A<int>(1);
    ```
    你看如果没有`<T>`这个类型参数的话,编译器无法在编译期间就检查类型错误,会导致不必要的类型转换和可能的类型错误,而 typescript 是微软的面向对象编程语言,在设计上会有同样的形式,所以你这里的这个`<T>`不能够省略的
    find456789
        9
    find456789  
    OP
       2020-05-28 16:08:17 +08:00
    @jswh
    @BingoXuan
    @eGlhb2Jhb2Jhbw

    哦 谢谢,似乎有一些明白了

    冒昧再请教一下

    问题 1: 如果我不加<T>, 编译器 有可能以为 T 是一个自定义的 interface 或者 type 对吗?

    问题 2: 如果我加了 <T>, 就是 先告诉编译器,接下来的 T 是个泛型,而不是自定义 interfa 、type, 对吗
    winnerczwx
        10
    winnerczwx  
       2020-05-28 17:18:18 +08:00 via iPhone
    在 c#里可以这样简写
    killergun
        11
    killergun  
       2020-05-28 20:34:56 +08:00
    看看 C#的泛型就知道了
    Jirajine
        12
    Jirajine  
       2020-05-28 20:45:51 +08:00 via Android
    泛型就是把类型参数化,<T>的意思是接收一个类型作为参数,后面的 T 是在使用这个参数。就像一般的变量把数据参数化一样。
    mxalbert1996
        13
    mxalbert1996  
       2020-05-28 21:23:24 +08:00 via Android
    楼主是不是以为泛型的类型只能用 T 表示?然而并不是。
    CosimoZi
        14
    CosimoZi  
       2020-05-28 21:25:48 +08:00
    有兴趣可以读点范畴论,对泛型的本质会有更深的理解.本质上像 lz 举例的带泛型的函数表达了自然变换(natural transformation),和一般的函数在数学意义上就不一样.
    aguesuka
        15
    aguesuka  
       2020-05-28 23:45:33 +08:00
    java 里面可以这样调用泛型函数 identity<MyType>(param); 在 param 是 lambda 的时候,有时尖括号是不能省略的
    BingoXuan
        16
    BingoXuan  
       2020-05-29 15:30:16 +08:00
    @find456789
    是的,泛型是根据范型使用的上下文推断的类型。如果泛型声明时离开了使用上下文,那就没有意义了。所以需要通过<T,...>声明,并传递给上下文使用。

    如果不结合运用泛型的上下文来声明,糟糕的例子就是 python3 的泛型了。简直就只多此一举。代码量一多,泛型声明就被淹没 了。具体类型和泛型用起来一毛一样。如下代码,你完全不知道有没有用到泛型,如果提前声明 T 是类型 str,那么扔一个 int 其实会报类型不正确的。

    def Add(a:T,b:T)->T
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3547 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 29ms · UTC 11:09 · PVG 19:09 · LAX 03:09 · JFK 06:09
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.