typescripttypescript-genericsgeneric-type-parameters

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


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?


Solution

  • <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.