What are the difference between generic Type(T) vs any in typescript

JavascriptAngularTypescriptGenericsTypes

Javascript Problem Overview


What is the difference between generic Type(T) vs any in typescript?

Function 1

function identity(arg: any): any {
    return arg;
}

Function 2

function identity<T>(arg: T): T {
    return arg;
}

Function 3

function identity<T>(arg: T[]): T[] {
    return arg;
}

>Function 1 & 3 is accepted if we passing any kind of data type, But the function 2 does not accept if we pass an array. generic type is accepting all kind of data type on compile time. but here why it does not accept?

Also which function is good for better performance ( function 1 or function 3)?

Javascript Solutions


Solution 1 - Javascript

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 - Javascript

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

Solution 3 - Javascript

The main usage of T is to avoid breaking the type when you call a method.

Example:

If you do :

let foo = new Foo();
identity(foo).bar();

The second line will be okay for the compiler, but not because he knows that bar exists in Foo type, because it's any, and any can have any method.

If you do :

let foo = new Foo();
identity<Foo>(foo).bar();
identity<Foo>(foo).notExistingMethod();

The second line will compile fine, not the third one because Foo doesn't have a notExistingMethod method.

any is often used when you need to create something in a more Javascript-way, meaning that you don't really know what is in your object, since Javascript doesn't have any types (I'm not talking about es6 ofc).

Solution 4 - Javascript

Everything is any on runtime and on top of that it's any at compile time in JavaScript. That's why there is TypeScript to provide type-safety at compile time.

The difference between any and T / T extends etc. is that you have type safety during compile time for example

protected typeSafety = <T extends String>(args:T):T =>{
    return args;
}

this.typeSafety(1); // compile error
this.typeSafety("string"); // good to go

If the function accepts anything you would have the error at runtime which would be too late.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionRamesh RajendranView Question on Stackoverflow
Solution 1 - JavascriptEstus FlaskView Answer on Stackoverflow
Solution 2 - JavascriptMiladView Answer on Stackoverflow
Solution 3 - JavascriptSupamiuView Answer on Stackoverflow
Solution 4 - JavascriptMurat KaragözView Answer on Stackoverflow