【问题标题】:Argument of type 'HTMLElement | null' is not assignable to parameter of type 'Element'. Type 'null' is not assignable to type 'Element'.ts(2345)'HTMLElement | 类型的参数null' 不可分配给“元素”类型的参数。类型“null”不可分配给类型“元素”.ts(2345)
【发布时间】:2020-08-21 10:00:41
【问题描述】:

我有 index.html

<body>
    <div id="portal"></div>
    <div id="root"></div>
</body>

并且想在portal divroot div 之外使用下面的组件,

import React from 'react';

const portalDiv = document.getElementById('portal');

function Portal1(props) {
  return ReactDOM.createPortal(
    <div>
      {props.children}
    <div/>, 
  portalDiv); //here
}

export default Portal1;

但是我得到了这个错误,'HTMLElement | 类型的参数null' 不可分配给“元素”类型的参数。 类型 'null' 不能分配给 VScode 中的类型 'Element'.ts(2345)

我正在使用打字稿。请帮忙。

【问题讨论】:

    标签: reactjs typescript react-dom


    【解决方案1】:

    其他人回答说你应该添加一个空检查,但是 Typescript 也有一个非空断言,当你确定通过添加 @ 值永远不会为空时,你可以使用它987654323@ 运算符到语句的末尾:

    const portalDiv = document.getElementById('#your-element')!;
    

    【讨论】:

    • 是的,确实不错。 (为了补充信息,一些时间,打字稿,可能是最新的,建议在同一个地方使用?而不是!。工作正常。
    • !回到你身边!我不知道上述 if () {} 解决方案在我的情况下是否可行(也许我只是不知道如何),因为 jsx 库(react-modal)期望回调返回一个 html 元素,而不是直接返回元素,所以我不知道在什么时候我可以完成检查并让 TS 识别它。很高兴你分享。我只是想知道我是否/何时会像这样滥用一些逃生舱口。我想成为用户而不是滥用者,但也许这就是他们创建它的原因。
    • 好吧,看看this example。第 7 行的 ! 检查是必需的,因为打字稿不够“聪明”,无法看到您已经在另一个函数中检查了该值是否不为空。
    • 这个操作员有点菜鸟,你能链接文档页面吗?
    【解决方案2】:

    所以我不知道是否还有人遇到这个问题,但有一个更简单直接的解决方案。 只需用 "as" 关键字声明模态元素
    const modalRoot = document.getElementById("modal-root") as HTMLElement; 这消除了错误。 我建议查看这个很棒的 react-typescript 备忘单。
    https://github.com/typescript-cheatsheets/react

    【讨论】:

    • 是的,这可能有效,但我们称其为内联类型转换,即我们只是在适当的位置更改类型。还是觉得,如果有null值,也就是div不存在,还是会给null。并且将 null 类型转换为 HTMLElement 可能会出错。您是否尝试应用更改?
    • 我确实应用了它,它似乎是修复错误的唯一方法。备忘单提供了有关为什么推荐此方法的更多详细信息。顺便说一句,HTMLElement 类型是 Element|null 类型,所以我认为它不会出错。我已经测试过了
    【解决方案3】:

    因为getElementById 可能返回null。所以你只需在使用之前检查一下:

    function Portal1({ children }) {
      return portalDiv ? ReactDOM.createPortal(<>{children}</>, portalDiv) : null;
    }
    

    【讨论】:

      【解决方案4】:

      getElementById 可以返回null,但createPortal 不接受null

      如果您知道门户 div 将存在,请在代码中明确说明:

      const portalDiv = document.getElementById('portal');
      if (!portalDiv) {
          throw new Error("The element #portal wasn't found");
      }
      

      这将允许 TypeScript 缩小常量的类型,删除类型的 | null 部分。如果有人更改了某些内容以使该代码不再运行时 div 不存在,它还会给您一个很好的主动警告。

      【讨论】:

        【解决方案5】:

        我认为最好的解决方案不是将其设为 nullHTMLDIVElement,而是将其设为用例 试图让打字稿知道 DivElement 目前可能是空的,但你会只需使用“!”即可承担责任符号。

        下面的代码示例:

        import React, {useEffect} from 'react';
        import ReactDOM from 'react-dom';
        import './modal-portlet.style.scss';
        
        const modalRoot = document.getElementById('modalRoot');
        
        type Props = {
          children: JSX.Element;
        };
        const ModalPortlet: React.FC<Props> = ({children}): JSX.Element => {
          const divContainer = window.document.createElement('div');
          divContainer.setAttribute('class', 'modal-container');
        
          useEffect(() => {
            /**********
             * immediately the component mount append @divContainer as the childNode of @modalRoot in the DOM
             **********/
            modalRoot!.appendChild(divContainer);
        
            return () => {
              modalRoot!.removeChild(divContainer);
            };
          });
        
          /************
           * return the createPortal api that takes the children(JSX) and inject it into @divContainer which is already a childNode of @modalRoot
           ************/
          return <>{ReactDOM.createPortal(children, divContainer)}</>;
        };
        
        export default ModalPortlet;
        

        【讨论】:

          【解决方案6】:

          我也遇到了同样的错误,所以我尝试了几种不同的方法,但对我有用的方法是处理 null 条件 即const portalDiv = document.getElementById('portal')!;

          【讨论】:

          • 是什么!做什么?
          猜你喜欢
          • 2020-03-08
          • 1970-01-01
          • 2021-09-06
          • 1970-01-01
          • 2021-09-09
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多