【问题标题】:What is the syntax for Typescript arrow functions with generics?带有泛型的 Typescript 箭头函数的语法是什么?
【发布时间】:2015-11-25 07:38:15
【问题描述】:

打字稿手册目前没有关于箭头功能的内容。正常功能 可以使用以下语法进行一般输入: 示例:

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

箭头函数的语法是什么?

【问题讨论】:

    标签: typescript


    【解决方案1】:

    语言规范在 p.64f 上说

    ( ... ) => { ... } 形式的构造可以被解析为 带有类型参数或类型断言的箭头函数表达式 应用于没有类型参数的箭头函数。它被解决为 前者[..]

    示例:

    // helper function needed because Backbone-couchdb's sync does not return a jqxhr
    let fetched = <
               R extends Backbone.Collection<any> >(c:R) => {
                   return new Promise(function (fulfill, reject) {
                       c.fetch({reset: true, success: fulfill, error: reject})
                   });
               };
    

    【讨论】:

      【解决方案2】:

      我发现上面的例子令人困惑。 我正在使用 React 和 JSX,所以我认为这会使场景复杂化。

      我从 TypeScript Deep Dive 那里得到了澄清,其中说明了箭头泛型:

      解决方法:在泛型参数上使用 extends 来提示编译器它是泛型的,这来自一个对我有帮助的更简单的示例。

          const identity = < T extends {} >(arg: T): T => { return arg; }
      

      【讨论】:

      • "T extends any" 将支持 void。
      • 虽然它工作得很好,但我必须说它看起来确实有点像黑客......
      【解决方案3】:

      解释语法 referenced by Robin... 的完整示例将它带回家:

      通用函数

      以下内容可以正常工作:

      function foo<T>(x: T): T { return x; }
      

      但是使用箭头泛型函数不会:

      const foo = <T>(x: T) => x; // ERROR : unclosed `T` tag
      

      解决方法:在泛型参数上使用 extends 来提示编译器 它是通用的,例如:

      const foo = <T extends unknown>(x: T) => x;
      

      【讨论】:

      • 是否可以为const foo 声明一些预定义的泛型类型?即type GenericFun&lt;T, A=T&gt; = (payload: A) =&gt; T; 然后在不提供T 类型的情况下使const foo: GenericFun 仍然是通用的?
      • 您的第二个示例只是.tsx 文件(TypeScript + JSX)中的错误。在.ts 文件中它可以正常工作,正如您在TypeScript playground 上看到的那样。
      • 较新的 typescript 编译器也支持尾随逗号 const foo = &lt;T,&gt;(x: T) =&gt; x; 以避开 JSX 的歧义。
      • @danvk 值得注意的是,这仅适用于那些在 TS 文件中禁止 JSX 的人 - 如果项目配置为允许 TS 文件中的 JSX,您仍然需要“扩展”或尾随逗号
      • 这就是要点:“使用 .ts 而不是 .tsx 扩展名”?
      【解决方案4】:

      这对我有用

      const Generic = <T> (value: T) => {
          return value;
      } 
      

      【讨论】:

      • 如果在.ts 文件中,这可行。否则必须延长。
      • 这对我在 vscode 中的 .ts 和 .tsx 文件中工作正常
      【解决方案5】:

      如果您在 .tsx 文件中,则不能只写 &lt;T&gt;,但这有效:

      const foo = <T, >(x: T) => x;
      

      extends {} hack 不同,这种hack 至少保留了意图。

      【讨论】:

      • 他们是否打算修复此行为?
      • 我想对此无能为力... JSX 和 Typescript 通用语法在这里发生冲突..
      • 太棒了 - 这是迄今为止最好的答案:完美运行,根本不会改变行为!
      • 默认类型参数类型呢? const foo = &lt;T = any,&gt;(x: T) =&gt; x 不起作用...
      • 为什么这个 hack 有效?在这种情况下,逗号是什么意思?
      【解决方案6】:

      虽然extends {} 的流行答案有效并且比extends any 更好,但它强制T 成为一个对象

      const foo = <T extends {}>(x: T) => x;
      

      为避免这种情况并保持类型安全,您可以改用extends unknown

      const foo = <T extends unknown>(x: T) => x;
      

      【讨论】:

        【解决方案7】:

        我使用这种类型的声明:

        const identity: { <T>(arg: T): T } = (arg) => arg;
        

        如果您需要,它允许为您的函数定义额外的道具,并且在某些情况下,它有助于使函数体从通用定义中保持清洁。

        如果你不需要额外的道具(命名空间之类的东西),它可以简化为:

        const identity: <T>(arg: T) => T = (arg) => arg;
        

        【讨论】:

        • 在函数体内使用&lt;T&gt; 时,这对我不起作用。 Typescript 告诉我&lt;T&gt; 没有用于函数定义位置的&lt;T&gt;,并告诉我它在函数体中我引用它的位置找不到&lt;T&gt;。使用 &lt;T,&gt; 'hack' 我没有这个问题。
        【解决方案8】:

        这么晚了,但是 ES6 不需要扩展它仍然对我有用.... :)

        let getArray = <T>(items: T[]): T[] => {
            return new Array<T>().concat(items)
        }
        
        let myNumArr = getArray<number>([100, 200, 300]);
        let myStrArr = getArray<string>(["Hello", "World"]);
        myNumArr.push(1)
        console.log(myNumArr)
        

        【讨论】:

        • 这对我不起作用,我必须像这样添加一个逗号:&lt;T, &gt;。如@jbmilgrom 回答下的@Thomas 评论中所述
        • 您应该在发布之前阅读其他解决方案。您的解决方案已经发布并附有解释。它仅适用于 .ts 文件,而不是 .tsx 文件。
        • 没有工作,因为没有逗号。 VSCode 捕获的语法错误
        【解决方案9】:

        2021 年,Ts 4.3.3

        const useRequest = <DataType, ErrorType>(url: string): Response<DataType, ErrorType> 
           => {
              ...
           }
        

        【讨论】:

        • move => 如果你愿意,可以移到上面 1 行
        【解决方案10】:

        当您尝试将 null 作为参数传递时,使用 会引发错误。我更喜欢使用 因为它可以解决问题。我还没有得到原因。但这对我有用。

        【讨论】:

          【解决方案11】:

          这对我有用

           const logSomething = <T>(something:T): T => {
                 return something;
              }
          

          【讨论】:

          • 但这已经被推荐过很多次了
          【解决方案12】:

          我知道我迟到了这个答案。但是考虑回答这个问题,以防其他人觉得它有帮助。没有一个答案提到如何将泛型与async 箭头函数一起使用。

          来了:

          const example = async <T> (value: T) => {
              //awaiting for some Promise to resolve or reject;
               const result = await randomApi.getData(value);
          
          } 
          

          【讨论】:

            【解决方案13】:

            为多个依赖的泛型类型添加示例:

            这个函数,转化为箭头函数如下:

            http.get = function <T = any, R = AxiosResponse<T>>(url: string, config?: AxiosRequestConfig): Promise<R> {
                        config.withCredentials = true;
                        ....
                      };
            

            注意扩展而不是等号:

            http.get = async <T extends any, R extends unknown = AxiosResponse<T>>(url: string, config?: AxiosRequestConfig): Promise<R> => {
                        config.withCredentials = true;
                        ...
                      };
            

            【讨论】:

              猜你喜欢
              • 2018-01-31
              • 2019-06-08
              • 2021-12-25
              • 2017-04-27
              • 1970-01-01
              • 2019-12-17
              • 2017-10-14
              • 1970-01-01
              相关资源
              最近更新 更多