在Typescript中,什么是<;T>;什么意思? 导出声明函数createEntityAdapter(选项?:{ selectId?:id选择器; sortComparer?:假|比较器; }):实体适配器;

在Typescript中,什么是<;T>;什么意思? 导出声明函数createEntityAdapter(选项?:{ selectId?:id选择器; sortComparer?:假|比较器; }):实体适配器;,typescript,c#,Typescript,C#,有人能给我解释一下这是什么意思吗?我知道是类型断言,但我不知道't'是什么。如果有人能向我解释这个函数在做什么,也会很有帮助 有人能给我解释一下这是什么意思吗 这就是类型脚本声明 摘录: 软件工程的一个主要部分是构建组件,这些组件不仅具有定义良好且一致的API,而且还具有可重用性。能够处理今天数据和明天数据的组件将为您提供构建大型软件系统的最灵活的能力 在C#和Java等语言中,工具箱中用于创建可重用组件的主要工具之一是泛型,也就是说,能够创建可以在多种类型而不是单一类型上工作的组件。这允许用户

有人能给我解释一下这是什么意思吗?我知道
是类型断言,但我不知道
't'
是什么。如果有人能向我解释这个函数在做什么,也会很有帮助

有人能给我解释一下这是什么意思吗

这就是类型脚本声明

摘录:

软件工程的一个主要部分是构建组件,这些组件不仅具有定义良好且一致的API,而且还具有可重用性。能够处理今天数据和明天数据的组件将为您提供构建大型软件系统的最灵活的能力

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

你提到:

我不知道什么是“不”

'T'
将是在运行时而不是编译时声明的类型。
T
变量可以是任何未声明的变量(我找不到引用,但我会假设可以用于变量名的任何有效字符集)。类似地,在中,如果类型
T
表示的不是值类型,而是更复杂的类型(类)或接口,则可以将其命名/声明为
TVehicle
TAnimal
,以帮助为未来的程序员表示有效的类型(并且可以被视为最佳实践,因为
T
并不直观)。我更喜欢
TSomething
,因为我知道大写的T表示泛型类型
WSometing
ASomething
也有效,但我不喜欢它。(微软的API几乎总是或举例来说)

如果有人能向我解释这个函数在做什么,也会很有帮助

这个函数什么都没做。这更像是声明一种可以有多个运行时类型值的函数类型。我不会解释这一点,而是直接从上面的链接中摘录

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

这可能会引出一个问题:

为什么使用泛型

Javascript有数组,但当您从数组中检索值时,它实际上可以是任何内容(typescript:
any
)。使用typescript,您可以通过如下方式声明类型安全:

// type of output will be 'number'
let output = identity(8675309);  
那么对于接口
Array
来说,还有什么比
T
更有意义呢?我不知道。我知道
T
必须是一种类型(数字、字符串等),因此使用
T
是有意义的,因为它是单词类型的第一个字母。我认为
Array
会让人困惑,如果type或type被保留或限制(目前
type
在某些上下文中有特殊意义,所以这也是一个糟糕的选择),那么避免使用它们是一个不错的选择。其他语言(,)也选择使用
T
,因此在语言之间切换并能够使用相同的术语是有利的

另一方面,下面这句话是什么意思

Array<number>
在前面的示例中,我(可能还有大多数开发人员)会假设Identity是一个现有类型,并且我无法更改它

interface Foo1 {
  bars: Array<Identity>;
}
Foo3
简直令人困惑

interface Foo3<Identity> {
  bars: Array<Identity>;
}
在使用约束时避免命名类型
type
的第一个原因是,它在方法中或在多个方法中都不能很好地读取。想象一下,日志记录方法比2行长得多,突然间,所有你读到的都是单词
Type

interface Lengthwise {
  length: number;
}

function loggingIdentity<Type extends Lengthwise>(arg: Type): Type {
  console.log(arg.length); 
  return arg;
}
纵向接口{
长度:数字;
}
界面宽度{
宽度:数字;
}
函数记录长度(参数:类型):类型{
控制台日志(参数长度);
返回arg;
}
函数记录宽度(参数:类型):类型{
控制台日志(参数宽度);
返回arg;
}
我认为以下内容更具可读性:

interface Lengthwise {
  length: number;
}

interface Widthwise {
  width: number;
}

function loggingLength<Type extends Lengthwise>(arg: Type): Type {
  console.log(arg.length);
  return arg;
}

function loggingWidth<Type extends Widthwise >(arg: Type): Type {
  console.log(arg.width);
  return arg;
}

纵向接口{
长度:数字;
}
界面宽度{
宽度:数字;
}
函数记录长度(arg:t长度方向):t长度方向{
控制台日志(参数长度);
返回arg;
}
函数记录宽度(参数:TWidthwise):TWidthwise{
控制台日志(参数长度);
返回arg;
}
其次,很可能会有超过1个泛型,这使得以下内容无效(希望是出于明显的原因)

纵向接口{
长度:数字;
}
界面宽度{
宽度:数字;
}
函数记录长度
(arg1:类型,arg2:类型){
console.log(arg1.length);
console.log(arg2.width);
}

虽然文档使用了
Type
来展示简单而平凡的示例,但我强烈建议不要在任何实际代码中使用
Type

您提供的示例是一个带有通用参数的函数。
T
(不必是
T
。您可以称之为
G
)被称为通用模板,在运行时替换
T
的实际类型

设想EntityAdapter具有以下实现:

interface Lengthwise {
  length: number;
}

interface Widthwise {
  width: number;
}

function loggingLength<Type extends Lengthwise, Type extends Widthwise>
(arg1: Type, arg2: Type) {
  console.log(arg1.length);
  console.log(arg2.width);
}

下面的代码返回一个EntityAdapter,其内容是
Car

let adapter1 = createEntityAdapter<any>(<parameters here>)
希望这能有所帮助。

遗憾的是,我没有“50点声誉”来参与排名靠前的答案下的精彩讨论,但值得注意的是,截至2021年3月,Typescript文档已经更新,不赞成在文档中使用
,赞成而不是

在我的例子中,这是令人困惑的,因为我找不到演示
t
用法的旧文档。然而,Erik Philips的回答帮助我了解到,这是以前在较旧(现在已弃用)的Typescript文档中展示的惯例

可能是
Array<Identity>
interface Foo1 {
  bars: Array<Identity>;
}
interface Foo2<T> {
  bars: Array<T>;
}
interface Foo3<Identity> {
  bars: Array<Identity>;
}
interface Foo4<TIdentity> {
  bars: Array<TIdentity>;
}
interface Lengthwise {
  length: number;
}

function loggingIdentity<Type extends Lengthwise>(arg: Type): Type {
  console.log(arg.length); 
  return arg;
}
interface Lengthwise {
  length: number;
}

interface Widthwise {
  width: number;
}

function loggingLength<Type extends Lengthwise>(arg: Type): Type {
  console.log(arg.length);
  return arg;
}

function loggingWidth<Type extends Widthwise >(arg: Type): Type {
  console.log(arg.width);
  return arg;
}

interface Lengthwise {
  length: number;
}

interface Widthwise {
  width: number;
}

function loggingLength<TLengthwise extends Lengthwise>(arg: TLengthwise): TLengthwise {
  console.log(arg.length);
  return arg;
}

function loggingWidth<TWidthwise extends Lengthwise>(arg: TWidthwise ): TWidthwise {
  console.log(arg.length);
  return arg;
}

interface Lengthwise {
  length: number;
}

interface Widthwise {
  width: number;
}

function loggingLength<Type extends Lengthwise, Type extends Widthwise>
(arg1: Type, arg2: Type) {
  console.log(arg1.length);
  console.log(arg2.width);
}

interface EntityAdapter<T> {
   save(entity: T);
}
let adapter1 = createEntityAdapter<any>(<parameters here>)
let adapter2 = createEntityAdapter<Car>(<parameters here>)
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`