Skip to content

Add ElementInternals, attachInternals from HTML standard #33218

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

Open
JanMiksovsky opened this issue Sep 3, 2019 · 12 comments
Open

Add ElementInternals, attachInternals from HTML standard #33218

JanMiksovsky opened this issue Sep 3, 2019 · 12 comments
Labels
Bug A bug in TypeScript Domain: lib.d.ts The issue relates to the different libraries shipped with TypeScript
Milestone

Comments

@JanMiksovsky
Copy link

TypeScript Version: 3.5.2

Search Terms: ElementInternals, attachInternals

Code

let internals: ElementInternals;

Expected behavior:
No errors. The ElementInternals interface and the related attachInternals method on HTMLElement are recent additions to the DOM spec. They are supported in Chrome 78 (scheduled for public release at the end of October 2019) and Edge canary builds.

Actual behavior:
Error Cannot find name 'ElementInternals'.

Playground Link: https://www.typescriptlang.org/play/#code/DYUwLgBAlgdmICcYENgGcBcECioC2IcAknIiugNwBQQA

@sandersn sandersn added Bug A bug in TypeScript Domain: lib.d.ts The issue relates to the different libraries shipped with TypeScript labels Sep 4, 2019
@sandersn sandersn added this to the Backlog milestone Sep 4, 2019
@AtEpoc
Copy link

AtEpoc commented Oct 9, 2021

I see #1149 merged. Does that mean the fix is coming soon?

@saschanaz
Copy link
Contributor

saschanaz commented Oct 10, 2021

I think it's #46222, but you don't have to wait and just go use https://www.npmjs.com/package/@types/web today. It's decoupled from typescript and thus updates happen separately.

@AtEpoc
Copy link

AtEpoc commented Oct 10, 2021

Thanks! @saschanaz
I installed @types/web, and syntax errors went away! But... the returned object from attachInternals() is missing ElementInternals.form, and all the methods described in MDN Web

Should I report that under 46222?

@saschanaz
Copy link
Contributor

.form and others are supported only on Chromium and thus are excluded for now, as MDN says.

@mitsusf
Copy link

mitsusf commented Oct 11, 2021

@saschanaz
Ok I see... TS is a superset of JS, but depends on browser support effort, some features are specifically hidden.

@btmurrell
Copy link

I do not understand how this has not been part of TypeScript yet. My team is developing W3C standard custom elements and the dirty secret is that custom elements by themselves do not play well in forms due to the inaccessibility of the shadow dom. ES6 and all modern browsers support HTMLElement.attachInternals, yet we cannot use it in TypeScript? Our team just tried to focus on fixing our components, and I am shocked that this is missing from TypeScript all this time.

We need this ASAP, so +1

@SntsDev
Copy link

SntsDev commented Apr 2, 2022

Meanwhile:

interface ElementInternalsExtended extends ElementInternals {
  readonly form: HTMLFormElement;
  readonly validity: ValidityState;
  readonly willValidate: boolean;
  readonly states: unknown;
  readonly validationMessage: string;
  readonly labels: NodeList;

  setFormValue: (
    value: File | string | FormData,
    state?: File | string | FormData
  ) => void;

  setValidity: (
    // A dictionary object containing one or more flags indicating the validity state of the element:
    flags?: {
      // A boolean value that is true if the element has a required attribute, but no value, or false otherwise. If true, the element matches the :invalid CSS pseudo-class.
      valueMissing?: boolean;

      // A boolean value that is true if the value is not in the required syntax (when type is email or url), or false if the syntax is correct. If true, the element matches the :invalid CSS pseudo-class.
      typeMismatch?: boolean;

      // A boolean value that is true if the value does not match the specified pattern, and false if it does match. If true, the element matches the :invalid CSS pseudo-class.
      patternMismatch?: boolean;

      // A boolean value that is true if the value exceeds the specified maxlength for HTMLInputElement or HTMLTextAreaElement objects, or false if its length is less than or equal to the maximum length. If true, the element matches the :invalid and :out-of-range CSS pseudo-classes.
      tooLong?: boolean;

      // A boolean value that is true if the value fails to meet the specified minlength for HTMLInputElement or HTMLTextAreaElement objects, or false if its length is greater than or equal to the minimum length. If true, the element matches the :invalid and :out-of-range CSS pseudo-classes.
      tooShort?: boolean;

      // A boolean value that is true if the value is less than the minimum specified by the min attribute, or false if it is greater than or equal to the minimum. If true, the element matches the :invalid and :out-of-range CSS pseudo-classes.
      rangeUnderflow?: boolean;

      // A boolean value that is true if the value is greater than the maximum specified by the max attribute, or false if it is less than or equal to the maximum. If true, the element matches the :invalid and :out-of-range and CSS pseudo-classes.
      rangeOverflow?: boolean;

      // A boolean value that is true if the value does not fit the rules determined by the step attribute (that is, it's not evenly divisible by the step value), or false if it does fit the step rule. If true, the element matches the :invalid and :out-of-range CSS pseudo-classes.
      stepMismatch?: boolean;

      // A boolean value that is true if the user has provided input that the browser is unable to convert.
      badInput?: boolean;

      // A boolean value indicating whether the element's custom validity message has been set to a non-empty string by calling the element's setCustomValidity() method.
      customError?: boolean;
    },
    // A string containing a message, which will be set if any flags are true. This parameter is only optional if all flags are false.
    message?: string,
    // An HTMLElement which can be used by the user agent to report problems with this form submission.
    anchor?: HTMLElement
  ) => void;
  
  checkValidity: () => boolean;
  reportValidity: () => boolean;
}
this.internals = this.attachInternals() as ElementInternalsExtended;

@jpzwarte
Copy link

@sandersn could this be given more priority? Webkit recently merged & enabled-by-default support for Form Associated Custom Elements as well. So it is now enabled by default in FF, Chromium and Webkit.

The current state is that attachInternals() and ElementInternals are already in TS, but additional things like states isn't. You have to typecast it as shown above.

@saschanaz
Copy link
Contributor

states does not exist because nobody implemented it except Blink. ElementInternals.prototype.states doesn't exist in Firefox nor in Safari, as it's not fully standardized yet. See also:

@justinfagnani
Copy link

Safari now ships custom states, and Firefox has it behind a flag: https://caniuse.com/mdn-api_customstateset

@KonnorRogers
Copy link

What I've been using for CustomStates:

declare global {
  interface ElementInternals {
    states: Pick<Set<string>, "size" | "add" | "clear" | "delete" | "entries" | "forEach" | "has" | "keys" | "values">
  }
}

export {}

https://tsplay.dev/WkqLPN

@dobrinyonkov
Copy link

states seems to be supported by Firefox nowdays, since its 126 version, actually https://caniuse.com/mdn-api_customstateset

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