ChatGPT解决这个技术问题 Extra ChatGPT

打字稿,如何传递“对象可能为空”错误?

我多次遇到“对象可能为空”错误,通常我使用安全的“if 语句”以防它返回空值。

我有以下功能:

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 && overlay.current ) { overlayEl.current.focus(); } 之前检查 null

S
Shanon Jackson

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

尝试....

 const overlayEl = useRef<HTMLDivElement>(null);

或者,如果您不关心它的未定义何时执行此类操作,则可以使用一些语法糖。

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; 
}

这种工作方式是打字稿静态分析足够聪明,可以找出 if 检查“防护”以防止 null,因此它将作为可能的类型从括号内的 null | HTMLDivElement 的联合中删除。


正如@thisismydesign 指出的那样,我认为在使用current 之前还必须检查null 是很重要的。
为打字稿提供更多信息是个好主意。
T
TargetTaiga
const overlayEl = useRef() as MutableRefObject<HTMLDivElement>;

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

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

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


谢谢你。至少对我来说,这是正确的答案。请注意,如果您的元素是输入,则需要使用 [...] = useRef() as MutableRefObject<HTMLInputElement>
谢谢,这个救了我。其他答案未考虑需要重新分配 .current 的情况
document.createElement("div") 将在第一次渲染时出错(关于文档的错误是 undefiend)
t
thisismydesign

如@Shanon Jackson 所述,向 ref 添加一个类型:

const linkRef = useRef<HTMLLinkElement>(null);

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

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

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

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


s
stackoverflow

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


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

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

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

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


Imo这是一个比标记答案更好的解决方案。
A
AbdulSamad

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

const myRef = useRef<HTMLLinkElement>(null);

myRef.current?.focus();

您可以在 caniuse 查看其浏览器支持。


N
Nikola Lukic

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

 (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
我不写这个,它来自问题。也许你是对的。
M
Maifee Ul Asad

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

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


k
kadiro

如果您不想给打字稿机会,请使用:

const iframe = useRef<HTMLIFrameElement | null>(null);

     if (
   typeof iframe !== "undefined" &&
   typeof iframe.current !== "undefined" &&
   iframe.current !== null
 ) {
   iframe?.current?.contentWindow='';
   );
 }

P
PeterMoelker

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

interface divEL {
  current: HTMLDivElement | null;
}

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

const overlayEl: divEL = useRef(null);

然后像这样添加焦点():

overlayEl.current!.focus();