Skip to content

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

@kirkwaiblinger

Description

@kirkwaiblinger

🔎 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 typescript-eslint/typescript-eslint#10461 (comment))

Metadata

Metadata

Assignees

No one assigned

    Labels

    Help WantedYou can do thisPossible ImprovementThe current behavior isn't wrong, but it's possible to see that it might be better in some cases

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions