Generic type parameter extending type "any" is not of type "any" anymore

433 views Asked by At

I was not able to find an answer to the question why function thisDoesNotWork causes an error. In contrast, function thisWorks transpiles the line anyArgs.whatever(); without complaining, and I would expect this to work in the other function, too.

function thisWorks(anyArgs: any): any { 
  console.log(anyArgs);
  anyArgs.whatever(); // NO ERROR
  return anyArgs;
}

function thisDoesNotWork<T extends any>(anyArgs: T): T { 
  console.log(anyArgs);
  anyArgs.whatever(); // ERROR: Property 'whatever' does not exist on type 'T'.
  return anyArgs;
}

Since T extends type any, T should be some sort of any, too, so why does the line anyArgs.whatever(); cause an error here?

1

There are 1 answers

3
Ovidijus Parsiunas On BEST ANSWER

<T extends any>(anyArgs:T) is not the same as (anyArgs:any). Generics add constrains to the type of values that are passed-in or returned from a method/function. So the generic <T extends any>(anyArgs:T) parameter tells the compiler that yes - anything can be passed in, however because it does not know what the type of T actually is ahead of time, it will not permit access or manipulation of the anyArgs value.

Hence, <T extends any>(anyArgs:T) is actually the same as <T>(anyArgs:T) rather than being same as (anyArgs:any).

As mentioned by @jcalz, this behaviour was only added to TypeScript in version 3.9 and previous versions did in fact regard extends any to be the same as any. Link to this change here.