javascript – TypeScript – ‘Element’不能分配给HTMLInputElement

我正在使用TypeScript和React.在我的组件(对话框窗口)中,我想存储触发器元素,例如按钮作为属性.当组件卸载时,我想将焦点返回到该元素.但是,我收到TSLint的错误,我不知道如何解决.

class Dialog extends React.Component<Props, {}> {
  ...
  focusedElementBeforeDialogOpened: HTMLInputElement;

  componentDidMount() {
    this.focusedElementBeforeDialogOpened = document.activeElement;
    ...
  }
  ...
}

我在分配属性值的行上收到错误:

[ts] Type 'Element' is not assignable to type 'HTMLInputElement'.
  Property 'accept' is missing in type 'Element'.

但是,如果我将属性的类型更改为Element甚至HTMLInputElement,我会在componentWillUnmount()中收到错误

componentWillUnmount() {
    ...
    this.focusedElementBeforeDialogOpened.focus();
}

此错误与Element类型没有focus()方法有关.

有没有办法告诉TypeScript document.activeElement应该是一个输入类型?就像是

this.focusedElementBeforeDialogOpened =< HTMLInputElement> document.activeElement;

或者是否有更好的方法来声明支持document.activeElement和.focus()的类型?

最佳答案 来自
document.activeElement的文档:

Often this will return an <input> or <textarea> object, if it has the text selection at the time. If so, you can get more detail by using the element’s selectionStart and selectionEnd properties. Other times the focused element might be a <select> element (menu) or an <input> element, of type button, checkbox or radio.

也就是说,document.activeElement不一定是HTMLInputElement的实例(它也可以是HTMLSelectElement等).

如果您确实只是在寻找HTMLInputElement,则可以使用TypeScript识别的简单实例type-guard:

componentDidMount() {
    if (document.activeElement instanceof HTMLInputElement) {
        this.focusedElementBeforeDialogOpened = document.activeElement;
    }
    ...
}

此外,您可以检测元素是否可聚焦,例如通过定义自己的类型保护:

interface IFocusableElement {
    focus(): void;
}

function isFocusable(element: any): element is IFocusableElement {
    return (typeof element.focus === "function");
}

然后使用IFocusableElement作为this.focusedElementBeforeDialogOpened的类型和您自己的类型保护:

focusedElementBeforeDialogOpened: IFocusableElement;

componentDidMount() {
    if (document.activeElement && isFocusable(document.activeElement)) {
        this.focusedElementBeforeDialogOpened = document.activeElement;
    }
    ...
}

如果您还需要Element提供的原始API,您可以使用交集类型:

focusedElementBeforeDialogOpened: IFocusableElement & Element;
点赞