【问题标题】:Why I need generic in Typescript为什么我需要 Typescript 中的泛型
【发布时间】:2017-12-10 18:49:44
【问题描述】:

在下面的示例中,我使用通用函数:

function Identity<T>(arg: T): T[] {

    return arg;
}

我可以这样写我的方法:

  function loggingIdentity(arg) {
          return arg;
    }

这两种方法都可以接受任何类型的值并返回任何值。对上述方法使用泛型有什么好处? 在其他示例中,我使用泛型创建了一个类:

class GenericNumber<T> {
    zeroValue: T;
    add: (x: T, y: T) => T;
}
let myGenericNumber = new GenericNumber<number>();
myGenericNumber.zeroValue = 0;
myGenericNumber.add = function(x, y) { return x + y; };

我可以在不使用泛型的情况下创建类和新对象:

 class GenericNumber {
        zeroValue;
        add: (x, y);
    }
    let myGenericNumber = new GenericNumber();
    myGenericNumber.zeroValue = 0;
    myGenericNumber.add = function(x, y) { return x + y; };

在 c# 语言中类型确定是强制性的,但在 typescript 中是可选的,我们可以在没有类型确定的情况下声明属性或变量或参数,它们可以是任何类型。

如果有人描述我在 typescript 中使用泛型的重要性和所有好处,我会很高兴。

【问题讨论】:

  • 你可以在 TypeScript 的任何地方使用any。但是你基本上是在使用 JavaScript,并且不再有任何类型安全性,这就是 TypeScript 存在的原因。 IDE 告诉您数组应该包含什么,并拒绝让您将字符串推送到 Array 中,这不是很好吗?

标签: .net class typescript generics


【解决方案1】:

在所有示例中,T 可以是任何类型,但所有Ts 都是相同类型。这很重要:让我们考虑一下您的 GenericNumber 课程。它有一个add 方法,它接受两个T 类型的参数并返回一个T。这可能是 add(x:number, y:number):numberadd(x:string, y:string):string - 但绝不是 add(x:string, y:Foo):boolean

此外,打字稿编译器会知道,如果您传入两个 numbers,该函数也会返回一个 number。这在函数的调用点可能是有价值的信息。

我还建议您阅读chapter on generics in the typescript handbook - 第一部分“Hello World of Generics”基本上回答了您的问题。

【讨论】:

    【解决方案2】:

    考虑简单的队列(先进先出)数据结构实现。一个简单的 TypeScript / JavaScript 看起来像:

      class Queue {
                    private data = [];
                    push = (item) => this.data.push(item);
                    pop = () => this.data.shift();
                   }
    

    这个实现的一个问题是它允许人们将任何东西添加到队列中,当他们弹出它时 - 它可以是任何东西。

         class Queue {
           private data = [];
           push = (item) => this.data.push(item);
           pop = () => this.data.shift();
          }
    
          const queue = new Queue();
          queue.push(0);
          queue.push("1"); // Oops a mistake
    

    // 开发者走进酒吧'

    console.log(queue.pop().toPrecision(1));
    console.log(queue.pop().toPrecision(1)); // RUNTIME ERROR
    

    一种解决方案是继续为这些约束创建特殊类。例如。一个快速而肮脏的号码队列:

     class QueueNumber
     {
         private data = [];
         push = (item: number) => this.data.push(item);
         pop = (): number => this.data.shift();
      }
    
              const queue = new QueueNumber();
              queue.push(0);
              queue.push("1"); // ERROR : cannot push a string. Only numbers allowed.
    

    您真正想要的是一种方式来说明无论被推送的内容是什么类型,对于弹出的任何内容都应该是相同的。 这可以通过一个通用参数轻松完成(在这种情况下,在类级别):

    /** 带有泛型参数的类定义 */

    class Queue<T> {
      private data = [];
      push = (item: T) => this.data.push(item);
      pop = (): T => this.data.shift();
    }
    

    使用泛型的一些方法

    1。泛型类

    通用类使用类型参数来定义一个可以处理不同数据类型的类。

    例如在下面的泛型类中 T 是类型参数。

    class Department<T>
    {
        //different types of employees
         private employees:Array<T>=new Array<T>();
         add(employee:T)
         {
        this.employees.push(employee);
         }
    }
    

    您可以定义一个与 HREmployee 类型一起使用的类:

    let hrDepartment:Department<HREmployee> = new :Department<HREmployee>();
    

    2。泛型函数

    泛型函数通过定义泛型参数来处理不同的数据类型。在下面的示例中,我们声明了一个名为 GenericFunction 的泛型函​​数。传递给此函数的类型称为 T。我们使用 T 来声明类型 传递给通用函数函数的参数。我们也使用 T 来声明函数的返回类型。

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

    您可以使用以下语法调用通用函数:

    GenericFunction<int>(1);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-03-08
      • 2013-05-13
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多