如何解决TS中的“对象可能为空”错误?

问题描述 投票:0回答:1

我使用带有React和Typescript的Draft.js与此thread存在类似的问题。使用与他们的文档示例相同的代码,在Object is possibly 'null'函数中出现focusEditor错误。即使当我检查空引用时,它仍然存在(就像上面引用的SO问题中的解决方案一样)。这是添加了空检查的代码:

import React from 'react';
import { Editor, EditorState } from 'draft-js';

export default () => {
  const [editorState, setEditorState] = React.useState(
    EditorState.createEmpty()
  );

  const editor = React.useRef(null);

  function focusEditor() {
    if (null === editor) {
      throw Error('editor is null') 
    }
    if (null === editor.current) {
      throw Error('editor.current is null') 
    }
    editor.current.focus(); // Error: Object is possibly 'null'
  }

  React.useEffect(() => {
    focusEditor()
  }, []);

  return (
    <div onClick={focusEditor}>
      <Editor
        ref={editor}
        editorState={editorState}
        onChange={editorState => setEditorState(editorState)}
      />
    </div>
  );
}

这应该足以重现该错误,我也安装了@types/draft-js,没有其他问题。

reactjs typescript draftjs
1个回答
0
投票

问题是editor被隐式设置为React.MutableRefObject<null>类型,该类型是具有current属性的对象,该属性保留传入的通用参数。因此,签名将类似于此:

interface MutableRefObject<T> {
  current: T | null
}

并且由于您传入了null,因此将通用参数推断为null。因此,这是editor.current应该能够保留的唯一值。

您应该通过将其传递为useRef<SomeType>()来明确告知TypeScript编译器您希望将其作为通用参数。您可以通过以某些类型安全为代价使用any作为通用参数来避开该问题,但最好还是声明该对象的类型将是什么。这是一个例子:

import React from 'react';

interface Focusable {
  focus: () => void
}

const editor = React.useRef<Focusable>(null);

function focusEditor() {
  if (null === editor) {
    throw Error('editor is null') 
  }
  if (null === editor.current) {
    throw Error('editor.current is null') 
  }
  editor.current.focus(); 
}

See on TypeScript Playground

我不确定要去的类型是什么,最好只使用HTMLElement而不是我作为示例创建的Focusable

无论如何,editor永远不会是null,因为它是一个常数。 React.useRef始终返回object,因此您可以删除第一张支票。因此,唯一可能是null的是editor.current。如果您不想引发错误,则只需执行一个沼泽标准的null保护,即可满足类型检查的要求:

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

可以使用nullish coalescing operator进一步缩短,因此您最终会得到以下结果:

import React from 'react';

const editor = React.useRef<HTMLElement>(null);

function focusEditor() {
  editor.current?.focus();
}

See on TypeScript Playground

© www.soinside.com 2019 - 2024. All rights reserved.