【问题标题】:Typescript, how to pass "Object is possibly null" error?打字稿,如何传递“对象可能为空”错误?
【发布时间】:2019-09-04 18:02:48
【问题描述】:

我多次遇到“Object is possible null”错误,通常我会使用安全的“if 语句”以防它返回 null。

我有以下功能:

const ModalOverlay = (props: any[]) => {
  const overlayEl = useRef(null);
    useEffect(() => {
    overlayEl.current.focus();
    });
    return <div {...props} ref={overlayEl} />;
  }

但是overlayEl.current 得到错误“对象未定义”。所以我试过了:

if (!overlayEl) {
    return null
  } else {
    useEffect(() => {
    overlayEl.current.focus();
    });
    return <div {...props} ref={overlayEl} />;
  }

这没有用。我也试过了:

overlay && overlayEl.current.focus();

任何提示将不胜感激!谢谢

【问题讨论】:

  • 您好,在尝试调用焦点方法if ( overlay &amp;&amp; overlay.current ) { overlayEl.current.focus(); }之前,您应该检查null

标签: typescript typescript-typings


【解决方案1】:

如果你真的知道在执行时你在这里没有错误,那么只需输入:

 (overlayEl as any).current 

如果没有,最好使用:

    if (typeof overlayEl !== 'undefined' &&
      typeof overlayEl.current !== 'undefined' &&
      overlayEl.current === null) {          
      return;
    }

    // Or

    try {
      // you code here ...
      // This is fine way to check by order -> parent.parent.FinalInstance
      // Also try & catch will handle all bad situation about current error
      overlay &&  overlayEl.current && overlayEl.current.focus();

    } catch(e){
       console.log("Real null >> ", e);     
    }

  // Suggest if i am wrong in syntax somewhere ,this is fast answer ;)

【讨论】:

  • 不幸的是 typeof null 等于 object 而不是 "null" 绝对不是 null
  • 我不写这个,它来自问题。也许你是对的。
【解决方案2】:

当你声明 const overlayEl = useRef(null); 将其输出为 null 的类型,因为这是它可以提供这么多信息的最佳推断,为 typescript 提供更多信息,它将按预期工作。

试试....

 const overlayEl = useRef<HTMLDivElement>(null);

如果你不关心它的 undefined 什么时候会做这样的事情,也可以选择一些语法糖。

const overlayEl = useRef(document.createElement("div"))

使用上述语法,所有常见的 DOM 方法都只返回默认值,例如“0”,即 overlayEl.offsetWidth、getBoundingClientRect 等。

用法:

if(overlayEl.current) {
    // will be type HTMLDivElement NOT HTMLDivElement | null
    const whattype = overlayEl.current; 
}

这种工作方式是 typescripts 静态分析足够聪明,可以发现 if 检查“守卫”以防止 null,因此它将作为可能的类型从这些括号内的 null | HTMLDivElement 的联合中删除。

【讨论】:

  • 我认为,正如@thisismydesign 所指出的,在使用current 之前,您还必须检查null,这一点很重要。
  • 为 typescript 提供更多信息是个好主意。
【解决方案3】:

如果你想“通过/跳过”,那么这会做到const overlayEl: any = useRef(null);

【讨论】:

  • 我刚刚做了......但它通过了! 总的来说,这听起来不是一个好建议。特别是,转换为 any 会危及拥有类型的目的——它使 overlayEl 任何类型都成为可能,因此所有类型信息都丢失了。 any 类型就像根本不类型(vanilla js)。
  • 是的,这是我发现的一种解决方法,只是为了让它工作。我没有说这是要走的路,或者是最好的:) 正如你所看到的,问题是“如何通过”,它可以表示“如何跳过”,而不是如何修复......但这是另一回事
  • 这真的不是一个好建议。你应该避免在打字稿中使用any。你还不如使用 javascript
  • 是的,我不喜欢任何人
  • 同样有效: const overlayEl = useRef(null as any);
【解决方案4】:
const overlayEl = useRef() as MutableRefObject<HTMLDivElement>;

它将overlayEl 转换为一个已启动的MutableRefObject,它是useRef 的返回值:

function useRef<T = undefined>(): MutableRefObject<T | undefined>;

然而在这种情况下,编译器会一直认为overlayEl 有一个值。

【讨论】:

  • 谢谢。至少对我来说,这是正确的答案。请注意,如果您的元素是输入,则需要使用 [...] = useRef() as MutableRefObject&lt;HTMLInputElement&gt;
  • 谢谢,这个救了我。其他答案没有考虑到需要重新分配 .current 的情况
  • document.createElement("div") 在第一次渲染时会出错(关于文档的错误是 undefiend)
【解决方案5】:

向@Shanon Jackson 提到的引用添加一个类型:

const linkRef = useRef<HTMLLinkElement>(null);

然后,确保在使用current 之前检查null 值:

if (linkRef.current !== null) {
  linkRef.current.focus();
}

这将满足 Typescript。而任何一个本身都不会。

使用any 或强制转换来“欺骗”编译器违背了使用Typescript 的目的,不要那样做。

【讨论】:

    【解决方案6】:

    您也可以使用 ES2020 中引入的optional chaining 来代替“if”语句以获得更简洁的代码

    const myRef = useRef&lt;HTMLLinkElement&gt;(null);

    myRef.current?.focus();

    你可以在caniuse查看它的浏览器支持。

    【讨论】:

      【解决方案7】:

      如果你不想给打字机会使用这个:

      const iframe = useRef<HTMLIFrameElement | null>(null);
      
           if (
         typeof iframe !== "undefined" &&
         typeof iframe.current !== "undefined" &&
         iframe.current !== null
       ) {
         iframe?.current?.contentWindow='';
         );
       }
      

      【讨论】:

        【解决方案8】:

        有时我们useRef 不仅保存一个元素,还保存一个像数据这样的值。不知何故,当我检查 if(something.current) return something.current 时即使 i 添加 && something.current!=null 也不起作用,所以我发现:

        something.current! 告诉 typescript i 知道有一个值并绕过这个问题。

        【讨论】:

          【解决方案9】:

          我认为这比这里的其他答案更简洁:

          const ModalOverlay = (props: any[]) => {
            const overlayEl = useRef<HTMLDivElement>(null);
            useEffect(() => {
              overlayEl.current!.focus();
            });
            return <div {...props} ref={overlayEl} />;
          }
          

          您指定引用的类型,并声明您知道它不为空。

          【讨论】:

          • Imo 这比标记的答案更好。
          【解决方案10】:

          取决于你喜欢什么,但一个好的语法和结构可能是创建一个接口:

          interface divEL {
            current: HTMLDivElement | null;
          }
          

          这将使您的声明保持清晰和简短,并且您可以将 divEl 接口重用于类似的 useRef 挂钩。

          const overlayEl: divEL = useRef(null);
          

          然后像这样添加focus():

          overlayEl.current!.focus();
          

          【讨论】:

            猜你喜欢
            • 2020-11-07
            • 1970-01-01
            • 2019-05-12
            • 2022-01-08
            • 1970-01-01
            • 2023-01-20
            • 2017-10-12
            • 2022-01-26
            • 1970-01-01
            相关资源
            最近更新 更多