What are the difference between generic Type(T) vs any in typescript
Solution 1:
There is no difference if this is identity function that just returns an argument and used without type restrictions:
const foo: any = fn(['whatever']);
And there is a difference for typed code:
const foo: string = fn('ok');
const bar: string = fn([{ not: 'ok' }]);
Also, the usage of generic type provides semantics. This signature suggests that the function is untyped and returns anything:
function fn(arg: any): any { ... }
This signature suggests that the function returns the same type as its argument:
function fn<T>(arg: T): T { ... }
Real functions are usually more meaningful than just return arg
example. Generic type can benefit from type restrictions (while any
obviously can't):
function fn<T>(arg: T[]): T[] {
return arg.map((v, i) => arg[i - 1]);
}
But the benefits become more obvious when the function is used in conjunction with other generic classes and generic functions (and eliminated if non-generics are involved):
function fn<T>(arg: T[]): T[] {
return Array.from(new Set<T>(arg));
}
This allows to consistently maintain T
type between input (argument) and output (returned value):
const foo: string[] = fn(['ok']);
const bar: string[] = fn([{ not: 'ok' }]);
There cannot be any difference in performance because TypeScript types exist only on design time.
Solution 2:
There is absolutely no performance difference while using any of those methods, because all of these fancy things are just Typescript
sugars and is only for development.
All the type checking is only in compile time ( when Typescript is transpiling/transforming your code back to normal javascript, in your server ).
Either way, when your code is shipped to the user's browser, this is how it looks :
function identity(arg){
return arg;
}
But to explain the differences :
When using any
you'll lose all type checking and safety checking that Typescript is offering, whereas, T
behaves like a variable that will hold the Type that you don't know what it is going to be.
So
function identity<T>(arg: T): T {
return arg;
}
In above, we know that if identify
accepts number
, it will return number
and so on, where as :
function identity(arg: any): any {
return arg;
}
But now, you don't know if arg
and the returned
value are the same type or not.
The other issue that T
will solve is when you're creating a method inside a class and it's expecting an argument which you want to make sure that this method will only accept arguments with the same type of the class's constructor's argument when instantiated.
export class MyClass<T>{
myMethod(anotherArg:T){}
}
So using above :
let str = "string";
let instance = new MyClass(str);
instance.myMethod("other string") // will compile
Where as :
let num = 32423423;
let instance = new MyClass(num);
instance.myMethod("other string") // won't compile