Fix Element.matches strict narrowing#2487
Conversation
|
Thanks for the PR! This section of the codebase is owned by @saschanaz - if they write a comment saying "LGTM" then it will be merged. |
|
@microsoft-github-policy-service agree |
|
|
||
| function emitElementMatchesMap() { | ||
| printer.printLine( | ||
| "type ElementMatchesMap<T, U> = { [K in keyof T as T[K] extends U ? U extends T[K] ? never : K : never]: T[K] };", |
There was a problem hiding this comment.
This is hard to parse, can you use something like ElementMap and ElementType than T and U? And also with parentheses.
It also kinda works weird, keyof ElementMatchesMap<HTMLElementTagNameMap, HTMLDivElement> is somehow "object" | "col" | "colgroup" | "embed" | "hr" | "iframe" | "img" | "input" | "legend" | "table" | "tbody" | "td" | "tfoot" | "th" | "thead" | "tr" ? It should be "div", right?
There was a problem hiding this comment.
Thanks, that makes sense. I updated the helper to make the strict-narrowing intent explicit with clearer names and a parenthesized mapped-type condition.
I also changed the narrowing map so same-type matches and structurally unrelated matches fall back to boolean. That covers the HTMLDivElement case you pointed out, so HTMLDivElement.matches("div") stays boolean and HTMLDivElement.matches("object") no longer gets a bogus type-guard path.
I added fixture coverage for the original false-branch regression, HTMLElement narrowing to HTMLDivElement, HTMLDivElement.matches("div") staying boolean, and HTMLDivElement.matches("object") not narrowing to HTMLObjectElement.
Fixes microsoft/TypeScript#63497.
This follows the direction discussed in that issue:
matches()should only act as a type guard when the selected tag's element type is a strict subtype of the current receiver type. For tags that map back to the same receiver type, it should still be accepted but returnboolean, so the false branch does not narrow the receiver tonever.Summary
Element.matches()type-predicate overloads to strict subtype matchesneverbehaviorValidation
npm run generatenpm testProperty 'id' does not exist on type 'never'; the patched baseline compiles cleanly