custom-elements-manifest icon indicating copy to clipboard operation
custom-elements-manifest copied to clipboard

fix: correct privacy and type propagation

Open nnaydenow opened this issue 8 months ago • 4 comments
trafficstars

In a child class, you can override both the visibility and type of a property from the parent class. For example, you can change a private property in the parent class to be public in the child class. Additionally, you can refine the type to a subset of the original type.

class Parent extends HTMLElement {
    /**
     * Some parent description
     * @private
     */
    test: boolean | string;
}

class Child extends Parent {
    /**
     * Some child description
     * @public
     */
    test: string;
}

export default Child;
export default Parent;

Updated example is added in: https://github.com/open-wc/custom-elements-manifest/pull/300#issuecomment-2765431791

nnaydenow avatar Mar 25 '25 11:03 nnaydenow

Deploy Preview for custom-elements-manifest-analyzer ready!

Name Link
Latest commit b96a8a716bbbd8c304c11b908e92211aba7d0ac9
Latest deploy log https://app.netlify.com/sites/custom-elements-manifest-analyzer/deploys/67e29758b464fc0008ffb615
Deploy Preview https://deploy-preview-300--custom-elements-manifest-analyzer.netlify.app
Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify site configuration.

netlify[bot] avatar Mar 25 '25 11:03 netlify[bot]

Hi @thepassle,

We have UI library that internally uses @custom-elements-manifest/analyzer to generate documentation pages for each component. Since it is not used only in our repo, but in many, could you please review it?

nnaydenow avatar Mar 25 '25 14:03 nnaydenow

@nnaydenow this one is kind of a unique use case and seems very problematic. I believe the changes you proposed would break the privacy inheritance for properties using the TypeScript access modifiers (private, protected, and public) and the JS private modifier (#) inheritance.

Is there a reason you're not able to use one of the standard access modifier techniques instead of using JSDoc tags?

break-stuff avatar Mar 28 '25 20:03 break-stuff

Hi @break-stuff,

Yes, our component templates are in separate TSX files, and using standard access modifiers causes TypeScript to complain about inaccessible properties.

You're also right that exposing a private property from a parent class in a child class can be problematic, as TypeScript’s inheritance chain doesn’t always account for what might come from the parent. However, my example may not have been the best illustration.

In our project, "private" and "protected" effectively mean the same thing: they indicate internal usage. These properties are not supported outside our organization and should not be used by developers consuming the library. In most cases, they are intended to be protected.

A common pattern in our project is using a base class for code reuse. For example, we have a ListItemBase class with a protected selected property. Various list item components—such as ListItemStandard and ListItemCustom—inherit from this base class. Only certain components expose selected as public since it is not meant to be controlled by applications in all situations.

That said, I’m curious—why is it that a child class can override everything except type and privacy? Could you share your thoughts on this? Why does this need to be enforced by the analyzer rather than being left to the consumer of the analyzer?


Update: For me the provided example a valid use case https://custom-elements-manifest.netlify.app/?source=Y2xhc3MgUGFyZW50IGV4dGVuZHMgSFRNTEVsZW1lbnQgewogICAgcHJvdGVjdGVkIHRlc3Q6IGJvb2xlYW4gfCBzdHJpbmc7Cn0KCmNsYXNzIENoaWxkIGV4dGVuZHMgUGFyZW50IHsKICAgIHB1YmxpYyB0ZXN0OiBzdHJpbmc7Cn0KCmV4cG9ydCB7CiAgICBDaGlsZCwKICAgIFBhcmVudCwKfTs%3D&library=vanilla

nnaydenow avatar Mar 31 '25 08:03 nnaydenow

Hey @break-stuff, if this approach doesn’t fully match your vision how this should work, do you think we could add a flag or config option to disable automatic inheritance?

nnaydenow avatar Nov 06 '25 12:11 nnaydenow

@nnaydenow would this scenario work for you?

class Parent extends HTMLElement {
    /**
     * Some parent description
     * @internal
     */
    test: boolean | string;
}

class Child extends Parent {
    /**
     * Some child description
     * @public
     */
    test: string;
}

export default Child;
export default Parent;

https://custom-elements-manifest.netlify.app/?source=Y2xhc3MgUGFyZW50IGV4dGVuZHMgSFRNTEVsZW1lbnQgewogICAgLyoqIEBpbnRlcm5hbCAqLwogICAgcHJvdGVjdGVkIHRlc3Q6IGJvb2xlYW4gfCBzdHJpbmc7Cn0KCmNsYXNzIENoaWxkIGV4dGVuZHMgUGFyZW50IHsKICAgIHB1YmxpYyB0ZXN0OiBzdHJpbmc7Cn0KCmV4cG9ydCB7CiAgICBDaGlsZCwKICAgIFBhcmVudCwKfTs%3D&library=vanilla

break-stuff avatar Nov 06 '25 13:11 break-stuff