Search code examples
typescripttypescript-generics

Why can't typescript infer class's method return type as generic


This is working correctly:

abstract class X<T extends Record<PropertyKey, any> > {
  abstract index(): T
}

class Y extends X<{name:string}> {
  index() {
    return {name:"Test"}
  }
}

But this causes an error:

abstract class X<T extends Record<PropertyKey, any> > {
  abstract index(): T
}

class Y extends X {
  index():{name:string} {
    return {name:"Test"}
  }
}

The error:

Generic type 'X' requires 1 type argument(s).ts(2314)

This might not be a problem but what if the class has more generic. Like this I need to retype EmptyObject for the generic even though it's the default.

type EmptyObject = Record<PropertyKey, never>

abstract class X<E extends Record<PropertyKey, any> = EmptyObject, T extends Record<PropertyKey, any> = EmptyObject> {
  abstract index(data: E): T
}

// I want to just do "extends X" and make typescript infer the rest
class Y extends X<EmptyObject, {name:string}> {
  index(data: EmptyObject): {name:string} {
    return {name:"Test"}
  }
}

Solution

  • TypeScript cannot currently infer a class's generic type argument from its implementation. It's a missing feature, requested in microsoft/TypeScript#39180. It's listed as "awaiting more feedback", meaning that they want to see a lot of community engagement and support for the feature before they consider implementing it. It's been around for a long time and there has been very little engagement, so I'd say it's quite unlikely for it ever to appear in the language. You could give it a 👍 and explain your use case, but it's probably not going to change anything.

    Type inference generally does not work that way in TypeScript. Generic type arguments are only inferred when you call a generic function. They are not inferred contextually. For the foreseeable future, you will need to manually specify the generic type arguments yourself.