如何解决 TS 中的 'Object possibly null' 错误?
How do I solve 'Object possibly null' error in TS?
我有与此 thread 类似的问题,使用 Draft.js 和 React 和 Typescript。
使用与他们的文档示例相同的代码,我在 focusEditor
函数中得到 Object is possibly 'null'
错误。即使在我检查空引用时它仍然存在(就像我上面引用的 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
,没有其他问题。
问题是 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();
}
我不确定去那里的预期类型是什么,最好只使用 HTMLElement
或者更具体的东西,比如 HTMLTextAreaElement
而不是 Focusable
我创建了一个例子。
无论如何,这可以改进:
React.useRef()
总是returns一个对象和editor
是一个常量,因此它不能被重新分配。这意味着它永远不会是 null
。您可以删除第一个支票。
唯一可能 null
的是 editor.current
。如果你不想抛出错误,你可以简单地做一个标准的 null guard 来满足类型检查:
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();
}
我有与此 thread 类似的问题,使用 Draft.js 和 React 和 Typescript。
使用与他们的文档示例相同的代码,我在 focusEditor
函数中得到 Object is possibly 'null'
错误。即使在我检查空引用时它仍然存在(就像我上面引用的 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
,没有其他问题。
问题是 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();
}
我不确定去那里的预期类型是什么,最好只使用 HTMLElement
或者更具体的东西,比如 HTMLTextAreaElement
而不是 Focusable
我创建了一个例子。
无论如何,这可以改进:
React.useRef()
总是returns一个对象和editor
是一个常量,因此它不能被重新分配。这意味着它永远不会是 null
。您可以删除第一个支票。
唯一可能 null
的是 editor.current
。如果你不想抛出错误,你可以简单地做一个标准的 null guard 来满足类型检查:
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();
}