generic Type(T)
与any
有什么区别?function identity(arg: any): any {
return arg;
}
function identity<T>(arg: T): T {
return arg;
}
function identity<T>(arg: T[]): T[] {
return arg;
}
功能1&amp;如果我们传递任何类型的
data type
,则接受3,但如果我们传递array
,则函数2不接受。 泛型类型在编译时接受所有类型的数据类型。但这里为什么不接受?
哪个功能有利于提高性能(功能1或功能3)?
答案 0 :(得分:22)
如果这是仅返回参数并且没有类型限制使用的标识函数,则没有区别:
const foo: any = fn(['whatever']);
输入代码有所不同:
const foo: string = fn('ok');
const bar: string = fn([{ not: 'ok' }]);
此外,泛型类型的使用提供了语义。此签名表明该函数是无类型的并返回任何内容:
function fn(arg: any): any { ... }
此签名表明该函数返回与其参数相同的类型:
function fn<T>(arg: T): T { ... }
实际功能通常比return arg
示例更有意义。通用类型可以受益于类型限制(而any
显然不能):
function fn<T>(arg: T[]): T[] {
return arg.map((v, i) => arg[i - 1]);
}
但是当函数与其他泛型类和泛型函数一起使用时,这些好处变得更加明显(如果涉及非泛型函数,则会被消除):
function fn<T>(arg: T[]): T[] {
return Array.from(new Set<T>(arg));
}
这允许在输入(参数)和输出(返回值)之间始终保持T
类型:
const foo: string[] = fn(['ok']);
const bar: string[] = fn([{ not: 'ok' }]);
性能不会有任何差异,因为TypeScript类型仅在设计时存在。
答案 1 :(得分:14)
使用任何这些方法时绝对没有性能差异,因为所有这些奇特的东西都只是Typescript
糖,仅用于开发。
所有类型检查仅在编译时(当Typescript将代码转换/转换回服务器中的普通javascript时)。
无论哪种方式,当您的代码发送到用户的浏览器时,它的外观如下:
function identity(arg){
return arg;
}
但要解释这些差异:
使用any
时,您将丢失所有类型检查和Typescript提供的安全检查,而T
的行为就像一个变量,它将保存您不会输入的类型知道它会是什么。
所以
function identity<T>(arg: T): T {
return arg;
}
在上文中,我们知道如果identify
接受number
,它将返回number
,依此类推,其中:
function identity(arg: any): any {
return arg;
}
但现在,您还不知道arg
和returned
值是否相同。
T
将解决的另一个问题是,当你在一个类中创建一个方法并且它期望一个你想要确保这个方法只接受参数的参数时实例化时类的构造函数的相同类型。
export class MyClass<T>{
myMethod(anotherArg:T){}
}
所以使用上面的内容:
let str = "string";
let instance = new MyClass(str);
instance.myMethod("other string") // will compile
其中:
let num = 32423423;
let instance = new MyClass(num);
instance.myMethod("other string") // won't compile
答案 2 :(得分:2)
运行时的所有内容都是any
,而any
在编译时它是JavaScript
。这就是TypeScript
在编译时提供类型安全的原因。
any
和T
/ T extends
等之间的区别在于您在编译期间具有类型安全性,例如
protected typeSafety = <T extends String>(args:T):T =>{
return args;
}
this.typeSafety(1); // compile error
this.typeSafety("string"); // good to go
如果函数接受了任何内容,那么在运行时就会出现错误,为时已晚。
答案 3 :(得分:2)
T
的主要用途是避免在调用方法时破坏类型。
示例:
如果你这样做:
let foo = new Foo();
identity(foo).bar();
第二行对于编译器是可以的,但不是因为他知道bar
类型中存在Foo
,因为它是any
和{{1}可以有任何方法。
如果你这样做:
any
第二行将编译正常,而不是第三行,因为let foo = new Foo();
identity<Foo>(foo).bar();
identity<Foo>(foo).notExistingMethod();
没有Foo
方法。
notExistingMethod
ofc)。