Skip to content

className is only included in HTMLElement, not Element #3220

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

Closed
kfranqueiro opened this issue May 19, 2015 · 9 comments
Closed

className is only included in HTMLElement, not Element #3220

kfranqueiro opened this issue May 19, 2015 · 9 comments
Labels
Bug A bug in TypeScript Domain: lib.d.ts The issue relates to the different libraries shipped with TypeScript Fixed A PR has been merged for this issue

Comments

@kfranqueiro
Copy link

@Arnavion pointed out to me that a recent update moved classList from HTMLElement up into Element, which is great.

However, className appears to still be only in HTMLElement. Is there a reason why? MDN at least seems to indicate that both should be common to Element.

It'd be great if this were moved up as well, as we currently need to cast when writing class manipulation APIs that should have no problem supporting Element (both HTMLElement and SVGElement). Given how these declarations are auto-generated though, I'm not sure what that would require.

@RyanCavanaugh RyanCavanaugh added Bug A bug in TypeScript Domain: lib.d.ts The issue relates to the different libraries shipped with TypeScript labels May 19, 2015
@RyanCavanaugh
Copy link
Member

@kfranqueiro
Copy link
Author

Tangentially, another colleague pointed out to me that the same problem exists with id (it's in the HTMLElement interface right now).

@mhegazy mhegazy added this to the TypeScript 1.6 milestone May 19, 2015
@duanyao
Copy link

duanyao commented May 20, 2015

The problem is, SVG elements has a different definition of className:

http://www.w3.org/TR/SVG/single-page.html#types-InterfaceSVGStylable

interface SVGStylable {
           readonly attribute SVGAnimatedString className;
}
interface SVGAnimatedString {
           attribute DOMString baseVal setraises(DOMException);
           readonly attribute DOMString animVal;
}
interface SVGElement : Element {}
interface SVGPathElement : SVGElement, SVGStylable { }

So it seems in SVGPathElement etc., Element::className is overridden by SVGStylable::className? This is not a big problem for JS, but TS currently doesn't allow overriding member's type of a super interface. What to do?

I also discussed this issue here #424 (comment) .

@zhengbli
Copy link
Contributor

Confirmed the current IE spec (from which the dom contents are generated) puts the className into HTMLElement. Also it is good point that @duanyao mentions, it may worth discussing whether to change the behavior or not.

@mhegazy
Copy link
Contributor

mhegazy commented May 21, 2015

@zhengbli looks like an IE spec issue.

@duanyao
Copy link

duanyao commented May 22, 2015

Looked into WebIDL spec and found that overriding of interface members is explicitly allowed:

Interfaces may specify an interface member that has the same name as one from an inherited interface. Objects that implement the derived interface will expose the member on the derived interface. It is language binding specific whether the overridden member can be accessed on the object.

Maybe it is desirable for TS to be aligned to this behavior, or sometimes it is awkward to translate WebIDL interfaces to TS ones.

Oh, it seems the situation of SVG*Element is a bit confusion:

Element (className as string)
      \
       SVGElement      SVGStylable (className as SVGAnimatedString)
                 \             /
                 SVGPathElement (className ?)

SVGElement extends Element but it doesn't redefine className; SVGStylable redefines className but it is not a sub interface of Element. How does the overriding occurs? Just because SVGStylable is lower than Element in the diagram?

Update:
In SVG 2, there is no SVGStylable anymore, and className: SVGAnimatedString is defined in SVGElement. However current lib.d.ts reflects SVG1.1.

@kfranqueiro
Copy link
Author

It does seem like for practical purposes at least, SVGElement would need a unique typing for className, even if it is available on Element as per the spec. My mistake for not realizing that initially.

(On the other hand, I think id could be safely raised into Element; it's a DOMString both for Element and SVGElement and is currently defined as a string for both HTMLElement and SVGElement in dom.generated.d.ts.)

@saschanaz
Copy link
Contributor

SVGElement spec does not extend DOM3 Element but DOM2 Element, which didn't have className property. Maybe we need something like interface DOM2Element...

Surprisingly even SVG2 spec uses DOM2.

@duanyao
Copy link

duanyao commented May 28, 2015

@saschanaz It looks like a bug of SVG2 spec for me, because the same spec references DOM4 in another place:

The SVG DOM requires complete support for DOM4 [DOM4]

Additionally, there is no multiple DOM implementaions with different levels in browsers, and the following expressions are both true:

Element.prototype.isPrototypeOf(SVGElement.prototype)
Element.prototype.isPrototypeOf(HTMLElement.prototype)

Update:

In latest SVG2 draft, SVGElement extends Element in DOM4. Interestingly, className: SVGAnimatedString is deprecated.

So maybe we can just remove className: SVGAnimatedString from SVGStylable and add className: string to Element. If someone want to use former, he/she can add a type assertion.
However, I think it is still worth considering to allow overriding members in super interfaces.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Bug A bug in TypeScript Domain: lib.d.ts The issue relates to the different libraries shipped with TypeScript Fixed A PR has been merged for this issue
Projects
None yet
Development

No branches or pull requests

6 participants