Typescript: ShadowRoot interface and attachShadow function are missing from type definitions

Created on 18 Aug 2016  路  13Comments  路  Source: microsoft/TypeScript

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.

lib.d.ts Fixed Suggestion

Most helpful comment

@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 { }

All 13 comments

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.

See: https://www.w3.org/TR/dom41/#shadowroot

Was this page helpful?
0 / 5 - 0 ratings

Related issues

nitzantomer picture nitzantomer  路  135Comments

RyanCavanaugh picture RyanCavanaugh  路  205Comments

Gaelan picture Gaelan  路  231Comments

jonathandturner picture jonathandturner  路  147Comments

disshishkov picture disshishkov  路  224Comments