microsoft / microsoft/TypeScript

misleading error message on invalid assignment when one type parameter extends another

Open
#60,881 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Domain: Error Messages Help Wanted Possible Improvement
Dominant language
Go
Stars
111k
Forks
14.3k
Avg merge
2d 4h
Merged PRs (30d)
132

Description

🔎 Search Terms

generic, type parameter, extends, arbitrary type which could be unrelated, assignment

🕗 Version & Regression Information
  • This changed between versions TS 3.8.3 and TS 3.9.7 (well, the pre-3.9 message isn't perfect, tbh but it only becomes fully wrong after that)
⏯ Playground Link

https://www.typescriptlang.org/play/?target=99&ts=5.8.0-dev.20241229&noUncheckedIndexedAccess=false#code/GYVwdgxgLglg9mABABwIYCdUFsCmUfoCiAHvmACYDOA8lABYEAKG2eBAPAMojIEAqAT14AaRNwBGg3ohykcFSmJ78hOAHwAKSsvRScALiW9dq0dsmrDEvQEpEAbwBQiRAHpXiPp0QBmAHQ+hnqIAOTcxnohiDCKYHBQiKiUlDAA5mCo4gA2OIhQcHmqodaqIX7Obq4V7p7e-gCsQUVhOpHRsfGJyWkZ2bn5hdItFrxliNUeLlNTLRGl7V0p6Zk5eQX0uRAIlFCYMGAJcMCDucORouIgCWfzWyBZ5Ijiufs7qAcwqPiPAO4w9IlEOQYMBgAR5AlzFAikdEFswDs9gdQvYAL5lCYTWq+PwATiaQ3CKlGCziCSSS16qwG0MJIBGOAxLhq02mNxJdweTxeCKg71gXxwv3+dESSAw4n+mHQAhOiB+dBgEFFnMez0Q4HQOCygseA1mxMZ5WZVRN2IALH4ABwE05EkwkmKIMmLHorfrrZolUbGyqstnexlwuD3NU8t4fXXykVixLoSW7DCy2m5BVKlUhrnqzXaqP6+2RX0s-3RMDIK5+KCUYgaACMonNtZsQUVihTKBYuHw6EQWDSdASYBwQtjAANZGQqIgAGqj4O8pFQX3mYIAXkQ2jmvAA3I5UUA

💻 Code
function parameterExtendsOtherParameter<SuperType, SubType extends SuperType>(superType: SuperType, subType: SubType) {
  // TS 3.3: Type 'SuperType' is not assignable to type 'SubType'.
  //
  // TS 3.5: Type 'SuperType' is not assignable to type 'SubType'. 
  //         'SuperType' is assignable to the constraint of type 'SubType', but 'SubType' could be instantiated with a different subtype of constraint '{}'.
  //
  // TS 3.9: Type 'SuperType' is not assignable to type 'SubType'.
  //         'SubType' could be instantiated with an arbitrary type which could be unrelated to 'SuperType'.
  //
  // TS 4.8: Type 'SuperType' is not assignable to type 'SubType'.
  //         'SubType' could be instantiated with an arbitrary type which could be unrelated to 'SuperType'.
  //         input.tsx(1, 41): This type parameter might need an `extends V` constraint.
  subType = superType;
}
🙁 Actual behavior
Type 'SuperType' is not assignable to type 'SubType'.
   'SubType' could be instantiated with an arbitrary type which could be unrelated to 'SuperType'.
   input.tsx(1, 41): This type parameter might need an `extends SubType` constraint.

The misleading thing here is that SubType plainly cannot be unrelated to SuperType. It's guaranteed to be a subtype of SuperType, since it extends SuperType.

🙂 Expected behavior

The TS 3.5 error message was nearly there (just swapped {} for SuperType)...

Type 'SuperType' is not assignable to type 'SubType'.
'SuperType' is assignable to the constraint of type 'SubType', but 'SubType' could be instantiated with a different subtype of constraint 'SuperType'.

I might suggest something like this instead though:

type 'SuperType' is not assignable to type 'SubType'. 
'SubType' is constrained to be a subtype of 'SuperType'.
input.tsx: You might have swapped the left and right hand sides of the assignment.

This is nearly a garden-variety instance of assigning a wider type to a narrower type, it just looks tricky because of the presence of generics and extends.

Additional information about the issue

contrast with this example:
(playground)

function parameterExtendsOrdinaryType<StringSubType extends string>(s: string, subType: StringSubType) {
  //  Type 'string' is not assignable to type 'StringSubType'.
  //   'string' is assignable to the constraint of type 'StringSubType', but 'StringSubType' could be instantiated with a different subtype of constraint 'string'
  subType = s;
}

cc @controversial (discovered in https://github.com/typescript-eslint/typescript-eslint/pull/10461#issuecomment-2524252783)

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the linked TypeScript Playground reproductions and compare the diagnostic for the generic assignment with the ordinary constrained-type example. Locate the compiler diagnostic path responsible for the wording, then add regression coverage for the reported case and verify that the resulting message explains the subtype constraint accurately.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
compilers
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.