custom-elements-manifest
custom-elements-manifest copied to clipboard
fix: correct privacy and type propagation
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
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...Use your smartphone camera to open QR code link. |
To edit notification comments on pull requests, go to your Netlify site configuration.
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 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?
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
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 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