Description
Search Terms
querySelector, return, type, selector
Suggestion
This issue closely follows #8114, which applies only to type selectors ("single-element selectors"). Related to #12568.
The return type of ParentNode#querySelector is Element
by default, but when the string argument matches exactly a lower-case element name, the return type is the interface of that element.
For example, .querySelector('#hero.wide')
returns an Element
type, but .querySelector('img')
returns an HTMLImageElement
type.
This helpful behavior fails beyond simple type selectors (a selector containing only an element name). When the argument becomes a compound selector, such as .querySelector('img#hero.wide')
, the return type is the more generic Element
. This is unhelpful when the element name, img
, remains in the selector.
My suggestion is to improve parsing of the string argument, so that when it is a compound selector that contains a type selector, the return type can still be a specific interface. Obviously, this would not apply to selectors not containing a type selector, e.g. there is no way to know for sure that .querySelector('#hero.wide')
is indeed an HTMLImageElement
.
Use Cases
document.querySelector('#hero.wide').src = '//example.com/hero.png' // Element
// Error: Property 'src' does not exist on type 'Element'
document.querySelector('img').src = '//example.com/hero.png' // HTMLImageElement
// no error, but cannot specify *which* image
document.querySelector('img#hero.wide').src = '//example.com/hero.png' // Element
// Error: Property 'src' does not exist on type 'Element'
(document.querySelector('img#hero.wide') as HTMLImageElement).src = '//example.com/hero.png'
// no error, and can specify which image, but must assert type manually
Summary: It would be nice for TS to infer that img#hero.wide
selects an HTMLImageElement
, based on the tag name img
in the selector. This would eliminate the need to assert the type manually.
Checklist
My suggestion meets these guidelines:
- This wouldn't be a breaking change in existing TypeScript/JavaScript code
- This wouldn't change the runtime behavior of existing JavaScript code
- This could be implemented without emitting different JS based on the types of the expressions
- This isn't a runtime feature (e.g. library functionality, non-ECMAScript syntax with JavaScript output, etc.)
- This feature would agree with the rest of TypeScript's Design Goals. (Specifically: Goals 5, 6, and 9)