-
Notifications
You must be signed in to change notification settings - Fork 12.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Node.parentElement should be Element, not HTMLElement #4689
Comments
This is arguable, because there was complainant before saying that it was too cumbersome to always cast the type For example, the return type of |
I just encountered this bug. The issue occurred with SVG on the page. Maybe this can be solved with generics? Though the syntax would be ridiculous. (e.g. |
How about changing |
sounds reasonable. |
I plan to submit a PR that contains the following changes:
interface DocumentOf<TNamesapce extends string, TElement extends Element, TDocumentElement extends TElement> extends Document {
documentElement: TDocumentElement;
getElementById(elementId: string): TElement;
getElementsByTagNameNS(namespaceURI: TNamesapce, localName: string): NodeListOf<TElement>;
}
type HTMLNamespace = "http://www.w3.org/1999/xhtml";
Any thoughts? |
note sure if you need the additional type DocumentOf. all you need is to redefine the two methods in HTMLDocument. |
The original idea of creating A common reason why developers want to "cast" an One of the advantages of using TypeScript is to reduce, if not eliminate, the chance of calling an undefined method or property unexpectedly. Returning a type that may be wrong during runtime appears to undermine this. A developer should be aware of the actual type of element that he/she is working on. With the introduction of the Back to the present issue, I suggest changing There may be additional issues to follow:
|
For 1, there has been a long discussion in #3613, the typings are not accurate, but looks like most ppl do not use SVG elements. |
Not sure if this is a separate or related issue, but (thanks to TS) I have gotten very comfortable writing vanilla DOM code, and wanted to try the same with SVG - and it doesn't seem like the type-definitions make much sense. For starters:
The type of Looks like the |
i ran into this when doing stuff with xml documents
this is the most arguable thing i've heard today is breaking types for all non-html documents really the best fix for this |
What's the status of this issue in 2019? Right now the method is defined |
Also see #32822. |
What's the status of this issue in 2020? While I understand the rationale behind the decision to make the type Or as a compromise, given the overwhelming majority use-case, I'd be in favor of making it a |
@jun-sheaf sent a PR for these changes and I've been reviewing about whether it should make it in for 4.1. I don't think we should make these changes, because it's going to add break a lot of code in a way that people won't think is to their advantage. TS tries to balance correctness and productivity and I think making The main crux of the PR is changes like these: - getElementById(elementId: string): HTMLElement | null;
+ getElementById<E extends Element = Element>(elementId: string): E | null; Meaning in the old version to use an SVG/XML element meant doing something like: const logo = document.getElementById("my-logo") as unknown as SVGPathElement Which isn't great, and now you can write: const logo2 = getElementById2("my-logo") as SVGPathElement
const logo3 = getElementById2<SVGPathElement>("my-logo") Which is better. But we lose something in the trade-off, and that is the tooling support for JS (because it always uses the defaults) With the changes to make it exactly the same as the spec, you can no-longer write code like: const logo4 = getElementById2("my-logo")!
logo4.innerText = "123" Without a cast, which would hit the TypeScript Website's codebase a few times (but I could switch to logo2.addEventListener("|
> "fullscreenchange" | "fullscreenerror" logo2.addEventListener("|
> "fullscreenchange" | "fullscreenerror" | "abort" | "animationcancel" | "animationend" | "animationiteration" | "animationstart" | "auxclick" | "blur" | "cancel" | "canplay" | ... 80 more ... | "paste" And this means you don't get a typed event anymore. Which I don't think is worth the change to Switching it to
But doesn't hinder the default JS tooling support. |
Hate to interject, as I do agree with your assessment of the trade-offs involved, but I would like to hear your opinion on making it a project-wide setting (#32822) - wouldn't that also alleviate the productivity/JS default issues? |
Personally, I'm super hesitant to add more flags and options to TS, there's already 100+ - but I'd let the TS team as a whole make that call IMO, the strictest/most compliant version can ship as a .d.ts which can modify the DOM types to be stricter globally though: // Default with lib.dom.d.ts
interface Document {
getElementById<E extends Element = HTMLElement>(elementId: string): E | null
}
// In something like in @types/strict-dom/index.d.ts
interface Document {
getElementById<E extends Element = Element>(elementId: string): E | null
}
const a = document.getElementById("e")!
a.innerText // bails Which means this can effectively live in user-land instead of it having to be inside the compiler, having a library means it can support more than just the recommendations here too |
Related question on Stack Overflow: Why isn't the |
The declaration of the
parentElement
property on theNode
interface inlib.d.ts
states that it is of typeHTMLElement
while it should beElement
(see the spec).The text was updated successfully, but these errors were encountered: