Unexpected overload signature rejection since TypeScript 4.8.x
See original GitHub issueBug Report
🔎 Search Terms
- This overload signature is not compatible with its implementation signature.
- HTMLElementTagNameMap
🕗 Version & Regression Information
- This changed between versions 4.7.4 and 4.8.2
⏯ Playground Link
Playground link with relevant code
💻 Code
export function childByTag<K extends Uppercase<keyof HTMLElementTagNameMap>>(
element: Element,
tagName: K,
): HTMLElementTagNameMap[Lowercase<K>] | null; // this overload is rejected
export function childByTag(element: Element, tagName: string): Element | null;
export function childByTag(element: Element, tagName: string): Element | null {
for (let i = 0; i < element.childElementCount; i++) {
if (element.children[i].nodeName === tagName) {
return element.children[i];
}
}
return null;
}
const anchor = childByTag(document.documentElement, 'A');
if (anchor) {
console.log(anchor.href); // Would be rejected without the first overload.
};
🙁 Actual behavior
TypeScript rejected the first function overload, because “This overload signature is not compatible with its implementation signature”.
🙂 Expected behavior
I didn’t expect the code to be rejected, because:
- To my understanding all the values in
HTMLElementTagNameMap
are subtypes ofElement
, thus being a covariant return type. - All the keys in
HTMLElementTagNameMap
are strings, thus matching a strict subset of all possible strings that may be passed totagName
. The remaining strings are matched by the second overload.
If the rejection is valid and my analysis is wrong, then I would have expected the error message to be more helpful in pointing out the problem.
Issue Analytics
- State:
- Created a year ago
- Reactions:2
- Comments:5 (2 by maintainers)
Top Results From Across the Web
Documentation - More on Functions - TypeScript
This overload signature is not compatible with its implementation signature. function fn ( x : number): boolean; This overload signature is not compatible...
Read more >Overload Signatures and the Implementation ... - Stack Overflow
Turns out in Typescript, the declaration of overload is not by having two methods with the same name and different signature with each...
Read more >TypeScript errors and how to fix them
error TS2349: Cannot invoke an expression whose type lacks a call signature. Type 'Promise ' has no compatible call signatures. Broken Code ❌....
Read more >Firebase JavaScript SDK Release Notes - Google
0 upgraded TypeScript only in the root. Fixed a bug that caused Firebase SDKs to throw an error in Firefox browsers when third-party...
Read more >@angular/animations | Yarn - Package Manager
angular-logo. Angular is a development platform for building mobile and desktop web applications using Typescript/JavaScript and other languages.
Read more >Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start FreeTop Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Top GitHub Comments
You can’t rewrite it to be more correct, no, since I’d say it’s already correct enough. But you can hack the typesystem to get the desired result with a workaround like
I have a similar problem in this version. Here’s an example signature with overloads as I originally wrote it. Note that there is a 2nd parameter,
whenKnown
which would either be not passed or be passed astrue
only.It seems that because the inputs are variable / overloaded, it’s finding errors with one or more of the callee overloads. Of course this works but hopefully it’s not the only way to work around this error:
So in the latest version, what’s the correct way to do this?