TypeScript: Issue a custom error message when trying to assign constraint type to generic type parameter

TypeScript Version: master

Search Terms: generic constrained type parameter error

Code

People are regularly confused why code like this doesn’t work:

function fn1<T extends string>(x: T): T {
  return "hello world!";
}

function fn2<T extends HTMLElement>(obj: T): T[] {
  return [obj, new HTMLDialogElement()];
}

function fn3<T extends boolean>(obj: T = false) {
}

Actual behavior: Unelaborated error like “Can’t assign false to T

Expected behavior:

If the source type is assignable to the constraint of a type parameter, we should issue a more specific error that attempts to explain the situation:

🚲 🏠

Type "false" is not assignable to type "T"
  "false" is assignable to the constraint type "boolean", but "T" could be a different more-specific type during a call

Playground Link: Link

About this issue

  • Original URL
  • State: closed
  • Created 6 years ago
  • Reactions: 28
  • Comments: 26 (11 by maintainers)

Commits related to this issue

Most upvoted comments

I find this error message undecipherable. I have lots of this type of error message:

‘A’ is assignable to the constraint of type ‘B’, but ‘B’ could be instantiated with a different subtype of constraint ‘{}’.

The last placeholder is always, the {}. I have no idea what this means or what the fix is.

Is it relevant to include some sort of “you should consider doing X, Y or Z to solve this problem” ?

It could speed up the process of finding a solution for new comers, as it is not really easy to understand, and there are not many available resources online,

I managed to found this : https://stackoverflow.com/a/56701587/6790372

Could you at least modify your first post in this issue, to explain why each case does not work, and what could be done instead ?

@RyanCavanaugh function fn1<T extends string>(x: T): T { return "hello world!"; } How to resolve this error? Change to return "hello world" as T?

My 2cents on this matter is that TS seems to punish you for using default params. Makes sense to me for this to be a warning instead.

@RyanCavanaugh says:

People are regularly confused why code like this doesn’t work:

function fn1<T extends string>(x: T): T {
 return "hello world!";
}

function fn2<T extends HTMLElement>(obj: T): T[] {
 return [obj, new HTMLDialogElement()];
}

function fn3<T extends boolean>(obj: T = false) {
}

So, did confused reduce after https://github.com/microsoft/TypeScript/pull/30394? I highly doubt it. Please describe this case in the documentation. At the moment you can find a sea of questions about this.

@moccaplusplus I agree that there is a fine balance between being informative and concise. IMO the extra information is helpful; as you can see I’ve been collating issues that trigger this error, so it’s something people definitely come across.

Generics are a hard subject, subtyping is a hard subject, and variance is a hard subject—this error is a combination of all three. I think spelling out the problem in a more concrete way is a definite improvement.