TypeScript Version: 1.8.0 / nightly (2.0.0-dev.201xxxxx)
Code
// A *self-contained* demonstration of the problem follows...
class CustomElement extends HTMLElement {
private shadowDom : ShadowRoot;
createdCallback() : void {
this.shadowDom = this.attachShadow({mode: "closed"});
}
}
Expected behavior:
ShadowRoot is recognized as a valid type, and the HTMLElement's attachShadow function is recognized as per the DOM standard.
Actual behavior:
Neither ShadorRoot nor the attachShadow functions are recognized.
The Shadow DOM is still not implemented in many browsers. Interfaces are open ended, so these can be declared yourself.
@Fairmill here's what I ended up using in my project: (based on https://www.w3.org/TR/shadow-dom/)
// shadow-dom.d.ts
declare global {
type ShadowRootMode = "open" | "closed";
interface ShadowRootInit {
mode: ShadowRootMode;
delegatesFocus?: boolean;
}
interface CaretPosition {
offsetNode: Node;
offset: number;
getClientRect(): ClientRect;
}
interface DocumentOrShadowRoot {
getSelection(): Selection | null;
elementFromPoint(x: number, y: number): Element | null;
elementsFromPoint(x: number, y: number): NodeListOf<Element>;
caretPositionFromPoint(x: number, y: number): CaretPosition | null;
activeElement: Element | null;
styleSheets: StyleSheetList;
}
interface ShadowRoot extends DocumentFragment, DocumentOrShadowRoot {
host: HTMLElement;
mode: ShadowRootMode;
}
interface Document extends DocumentOrShadowRoot {}
interface AssignedNodesOptions {
flatten: boolean = false;
}
interface HTMLSlotElement extends HTMLElement {
name: string;
assignedNodes(options?: AssignedNodesOptions): NodeList;
}
interface Element {
attachShadow(shadowRootInitDict: ShadowRootInit): ShadowRoot;
assignedSlot: HTMLSlotElement | null;
slot: string;
shadowRoot: ShadowRoot | null;
}
}
export { }
Could this be revisited? V1 seems a lot better on caniuse - http://caniuse.com/#feat=shadowdomv1
@kitsonk
Please consider reopening this issue -- ShadowDOM V1 support is now imminent in FireFox and has already landed in Chrome and Safari:
I agree. This issue is at a point where it should be revisited soon.
@klebba I am not part of the TypeScript team.
And the issue is still open.
This should be fixed in typescript@next already.
@mhegazy : It looks like ShadowRoot still isn't implemented in the library declarations, or getRootNode() seems to return the wrong type (Node instead of ShadowRoot).
When I write ...
let h = this.getRootNode().host;
... I get a TS2339 compiler error: "Property 'host' not available for type 'Node'."
me too, the version of ts is [email protected]. Property 'createShadowRoot' does not exist on type 'HTMLElement'銆俬ow to solve it?
In the meantime I got a great explanation why this doesn't work the way we all expect:
https://github.com/whatwg/dom/issues/739
MDN already updated their docs to clarify the situation.
Until TypeScript corrects their lib, we'll have to
declare global {
interface Node {
getRootNode(options?: GetRootNodeOptions): Node|ShadowRoot;
}
}
Actually, Node is a base class of ShadowRoot. So, the current interface is correct.
Most helpful comment
@Fairmill here's what I ended up using in my project: (based on https://www.w3.org/TR/shadow-dom/)