在Typescript中,<T>是什么意思?

Sno*_*lax 30 typescript

export declare function createEntityAdapter<T>(options?: {
    selectId?: IdSelector<T>;
    sortComparer?: false | Comparer<T>;
}): EntityAdapter<T>;
Run Code Online (Sandbox Code Playgroud)

有人可以向我解释一下这意味着什么?我知道<>是类型断言,但我不知道是什么'T'.如果有人可以向我解释这个功能正在做什么,这也会很有帮助.

Eri*_*ips 57

有人可以向我解释一下这意味着什么?

那是打字稿泛型声明.

摘抄:

软件工程的一个主要部分是构建组件,这些组件不仅具有定义明确且一致的API,而且还可以重用.能够处理当前数据以及未来数据的组件将为您提供构建大型软件系统的最灵活功能.

在像C#和Java这样的语言中,工具箱中用于创建可重用组件的主要工具之一是泛型,即能够创建可以在多种类型而不是单个类型上工作的组件.这允许用户使用这些组件并使用他们自己的类型.

.

我不知道'T'是什么.

<T>将是在运行时而不是编译时声明的类型.该'T'变量可以是任何非声明的变量(我无法找到一个参考,但我会承担任何有效的组可用于变量名的字符).类似地,在,如果类型T表示不是值类型而是更复杂的类型(类)或接口,则它可以被命名/ delcared为TTVehicle帮助表示未来程序员的有效类型(并且可以被认为是最佳实践,因为只是TAnimal不直观).我更喜欢,T因为我知道大写字母T表示泛型类型. TSomething或者WSometing也有效,但我不喜欢它.(微软API几乎总是TContextTEntity).

如果有人可以向我解释这个功能正在做什么,这也会很有帮助.

那么功能没有任何事情.这更多地声明了一种可以具有多个运行时类型值的函数.我将包括一个直接从上面的链接中摘录的摘录,而不是解释.

function identity<T>(arg: T): T {
  return arg;
}
Run Code Online (Sandbox Code Playgroud)

可以使用如下:

// type of output will be 'string'
let output = identity<string>("myString");  
Run Code Online (Sandbox Code Playgroud)

要么

// type of output will be 'string', the compiler will figure out `T`
// based on the value passed in
let output = identity("myString");  
Run Code Online (Sandbox Code Playgroud)

要么

// type of output will be 'number'
let output = identity(8675309);  
Run Code Online (Sandbox Code Playgroud)

哪个可能会提出这个问题:

为什么要使用泛型

好吧Javascript有数组,但是当你从数组中检索一个值时,它实际上可以是任何东西(typescript :) ASomething.使用打字稿,您可以通过声明类型来获得类型安全:

 // Array<T>
 let list: number[] = [1, 2, 3];
 // or 
 let list: Array<number> = [1, 2, 3];
Run Code Online (Sandbox Code Playgroud)

现在,数组中的每个值都有一个类型.如果您尝试将字符串放入此数组中,Typescript将抛出编译时错误.当您检索值时,您会获得类型安全性和智能感知(取决于您的编辑器):

class Person {
  FirstName: string;
}

let people: Array<Person> = [];
people.push({ FirstName: "John" } as Person);

let john = people.pop();  
// john is of type Person, the typescript compiler knows this
// because we've declared the people variable as an array of Person

console.log(john.FirstName);  
Run Code Online (Sandbox Code Playgroud)

声明类型的通用约束.开放 - 封闭原则的一个很好的例子.

在面向对象的编程中,开放/封闭原则指出"软件实体(类,模块,函数等)应该是开放的,但是对于修改是封闭的"; [1]也就是说,这样的实体可以允许它的行为在不修改源代码的情况下进行扩展.

在下面的示例中,任何人都可以扩展Human或Cheeah,甚至可以创建自己的派生类型,Logger功能可以继续工作而无需任何修改.

interface IAnimal {
  LegCount: number;
}

class Cheetah 
  implements IAnimal {
  LegCount: number = 4;
}

class Human
  implements IAnimal {
  LegCount: number = 2;
}

public class Logger<TAnimal extends IAnimal> {
  public Log(animal: TAnimal) {
    console.log(animal.LegCount);
  }
}

var logger = new Logger();
var human = new Human();
logger.Log(human);      
Run Code Online (Sandbox Code Playgroud)

工作实例

在前面的示例中,我使用了通用约束来限制any程序员可以使用的类型来创建TAnimal从接口派生的类型的实例Logger.这允许编译器验证IAnimal类始终假定类型具有属性Logger.

  • 菲利普斯我也见过<R>和<U>.这些是什么意思,或者我可以使用有角度的括号内的任何字符? (4认同)
  • @CharlesRobertson 更新了答案,感谢这对未来的读者有帮助,很好的问题。 (3认同)
  • @jcarlosweb 更新了我的答案,希望它能回答您的问题。 (2认同)

Jus*_*rty 9

遗憾的是,我没有在@Erik Philips的最高评价答案下为出色的讨论做出贡献所需的“50 个声望点” ,但值得注意的是,截至 2021 年 3 月,Typescript 文档已更新为不赞成<T>在文档中使用 ,而使用<Type>. 关联

就我而言,这令人困惑,因为我找不到演示T. 但是,Erik Philips 的回答帮助我理解,这是以前在较旧(现已弃用)的 Typescript 文档中展示的约定。

更新当前答案以包含此信息可能会有所帮助。

  • 虽然文档中包含“Type”的使用,但我添加了*不使用它的重要理由*。 (2认同)

小智 9

它被称为泛型,帮助我们编写安全而灵活的函数。它为类型提供变量。简而言之,您可以创建适用于不同类型的函数、接口或类,而无需预先指定类型。下面一些演示代码来解释我们为什么使用它以及如何使用它。

// any is too general ,and it loses the meaning of using typescript

function insertAtBegining(array:any[],value:any) {
    let newArr = [value, ...array];
    return newArr;
}

// if we specify the type number , this function will lost it's utility 

function insertAtBegining(array:number[],value:number) {
    let newArr = [value, ...array];
    return newArr;
}

// if we specify the type string , this function will lost it's utility 

function insertAtBegining(array:string[],value:string) {
    let newArr = [value, ...array];
    return newArr;
}

const demoArr = [1, 2, 3];

const updatedArr = insertAtBegining(demoArr, 4);
// more generic functions

function insertAtBegining<T>(array:T[],value:T) {
    let newArr = [value, ...array];
    return newArr;
}
Run Code Online (Sandbox Code Playgroud)


Emi*_*ker 6

您提供的示例是具有通用参数的函数. T(不一定是T.你可以调用它G.)被称为通用模板,其中实际的类型T在运行时被替换.

想象一下EntityAdapter有以下实现:

interface EntityAdapter<T> {
   save(entity: T);
}
Run Code Online (Sandbox Code Playgroud)

下面的代码返回一个内容为的EntityAdapter any.any可以是数字,字符串,对象或任何东西.

let adapter1 = createEntityAdapter<any>(<parameters here>)
Run Code Online (Sandbox Code Playgroud)

下面的代码返回一个内容为的EntityAdapter Car.

let adapter2 = createEntityAdapter<Car>(<parameters here>)
Run Code Online (Sandbox Code Playgroud)

基本上Car更具体any,你可以获得额外的类型安全.那么这有什么用呢?

简而言之,通用模板可以为您提供额外的类型安全性.例如,

adapter1.save('I am string') // this works because `T` is `any`
adapter1.save(new Car()) // this also works because `T` is `any`

adapter2.save('I am string') // this wont works  because `T` is `Car`, typescript compiler will complains
adapter2.save(new Car()) //this works because `T` is `Car`
Run Code Online (Sandbox Code Playgroud)

希望这可以帮助.

  • @CharlesRobertson 是的,你是对的。就打字稿而言,它们没有任何特殊含义。 (2认同)
  • 为了清楚起见,如果我理解正确的话,T 只是以后类型使用的占位符。那是对的吗? (2认同)