stencil
stencil copied to clipboard
bug: Interface ‘HTMLMyButtonElement’ cannot simultaneously extend types ‘MyButton’ and ‘HTMLStencilElement’. Named property ‘focus’ of types ‘MyButton’ and ‘HTMLStencilElement’ are not identical
Prerequisites
- [x] I have read the Contributing Guidelines.
- [X] I agree to follow the Code of Conduct.
- [X] I have searched for existing issues that already report this problem, without success.
Stencil Version
3.0.1
Current Behavior
Can't compile Stencil because of the typescript error
Error: Interface 'HTMLMyButtonElement' cannot simultaneously extend types 'MyButton' and 'HTMLStencilElement'. Named property 'focus' of types 'MyButton' and 'HTMLStencilElement' are not identical.
Interface 'HTMLMyButtonElement' cannot simultaneously extend types 'MyButton' and 'HTMLStencilElement'.Named property 'focus' of types 'MyButton' and 'HTMLStencilElement' are not identical.
'./src/components.d.ts'
interface HTMLMyButtonElement extends Components.MyButton, HTMLStencilElement {
}
Steps to Reproduce
I want to focus the button element which is inside the my-button, when my-button.focus() is called. Here is the code
@Component({
tag: 'my-button',
styleUrl: 'my-button.scss',
shadow: true,
})
export class MyButton {
buttonRef: HTMLButtonElement;
@Prop() disabled = false;
@Method()
async focus() {
this.buttonRef.focus();
}
render() {
return (
<button
ref={el => (this.buttonRef = el)}
disabled={this.disabled}
>
<slot />
</button>
);
}
}
Any ideas how to solve this without modifying typescript config file by adding : compilerOptions > "skipLibCheck": true,
Hey @Unluckynerd 👋
Can you please provide a full minimal reproduction case for us? I am unable to reproduce the error with the code snippet provided alone.
Thanks for the issue! This issue has been labeled as needs reproduction. This label is added to issues that need a code reproduction.
Please reproduce this issue in an Stencil starter component library and provide a way for us to access it (GitHub repo, StackBlitz, etc). Without a reliable code reproduction, it is unlikely we will be able to resolve the issue, leading to it being closed.
If you have already provided a code snippet and are seeing this message, it is likely that the code snippet was not enough for our team to reproduce the issue.
For a guide on how to create a good reproduction, see our Contributing Guide.
Thanks!
I can see what's happening now - MyButton#focus has a type of () => Promise<void>, which is colliding with HTMLElement provided by TypeScript's lib.dom.dts - focus(options?: FocusOptions): void;. Specifically, the return types are the issue. The former returns a Promise<void>, where the latter returns void.
Since focus is a reserved public name, and Stencil @Methods need to be marked as async, I would recommend renaming MyButton#focus to another name that does not conflict
@rwaskiewicz If I want to use the focus name, Can i use this workaround? Is this right way?
Here I am overriding the MyButton#focus in the constructor.
@Component({
tag: 'my-button',
styleUrl: 'my-button.scss',
shadow: true,
})
export class MyButton {
constructor(){
this.hostElement.componentOnReady().then(() => {
this.hostElement.focus = () => this.buttonRef.focus();
});
}
@Element() hostElement;
buttonRef: HTMLButtonElement;
@Prop() disabled = false;
@Event() zClick: EventEmitter;
handleClick(event) {
if (this.disabled) {
event.preventDefault();
event.stopPropagation();
} else {
this.zClick.emit(event);
}
}
render() {
return (
<button
ref={el => (this.buttonRef = el)}
disabled={this.disabled}
onClick={event => this.handleClick(event)}
>
<slot />
</button>
);
}
}
Heres the repo link
@Unluckynerd we do not recommend overriding the existing methods available on HTMLElement, such as focus.
In your example, it would be recommended to listen to the focus event from the host and then calling the focus() method from the button reference.
@sean-perkins is correct here. We're going to leave this open so that we can see if there are some better options for improving the error messaging here
Having a similar issue where I want to narrow the role attribute to a union type, but it conflicts with HTMLElement's role: string, but it feels like something a custom element should be able to do?