static createProperty(name, options = defaultPropertyDeclaration) {
        // Note, since this can be called by the `@property` decorator which
        // is called before `finalize`, we ensure storage exists for property
        // metadata.
        this._ensureClassProperties();
        this._classProperties.set(name, options);
        // Do not generate an accessor if the prototype already has one, since
        // it would be lost otherwise and that would never be the user's intention;
        // Instead, we expect users to call `requestUpdate` themselves from
        // user-defined accessors. Note that if the super has an accessor we will
        // still overwrite it
        if (options.noAccessor || this.prototype.hasOwnProperty(name)) {
            return;
        }
        const key = typeof name === 'symbol' ? Symbol() : `__${name}`;
        const descriptor = this.getPropertyDescriptor(name, key, options);
        if (descriptor !== undefined) {
            Object.defineProperty(this.prototype, name, descriptor);
        }
    }
Creates a property accessor on the element prototype if one does not exist
and stores a PropertyDeclaration for the property with the given options.
The property setter calls the property's `hasChanged` property option
or uses a strict identity check to determine whether or not to request
an update.

This method may be overridden to customize properties; however,
when doing so, it's important to call `super.createProperty` to ensure
the property is setup correctly. This method calls
`getPropertyDescriptor` internally to get a descriptor to install.
To customize what properties do when they are get or set, override
`getPropertyDescriptor`. To customize the options for a property,
implement `createProperty` like this:

static createProperty(name, options) {
  options = Object.assign(options, {myOption: true});
  super.createProperty(name, options);
}

@nocollapse