如何抑制'错误TS2533:对象可能是'或& # 39;未定义# 39;“?

我有一个type:

type tSelectProtected = {
handleSelector?: string,
data?: tSelectDataItem[],


wrapperEle?: HTMLElement,
inputEle?: HTMLElement,
listEle?: HTMLElement,
resultEle?: HTMLElement,


maxVisibleListItems?: number
}

我声明了一个全局模块变量:

var $protected : tSelectProtected = {};

我在function1()范围内赋值:

$protected.listEle = document.createElement('DIV');

稍后在function2()作用域中,我将调用:

$protected.listEle.classList.add('visible');

我得到TypeScript错误:

error TS2533: Object is possibly 'null' or 'undefined'

我知道我可以使用if ($protected.listEle) {$protected.listEle}来进行显式检查以使编译器平静下来,但这对于大多数非平凡的情况来说似乎非常不方便。

在不禁用TS编译器检查的情况下如何处理这种情况?

749720 次浏览

如果你知道类型永远不会是nullundefined,你应该声明它为foo: Bar而不带?。用? Bar语法声明一个类型意味着它可能是未定义的,这是你需要检查的。

换句话说,编译器正在做你要求它做的事情。如果您希望它是可选的,您稍后需要检查。

这个特性被称为“严格空检查”,关闭它确保没有设置--strictNullChecks编译器标志。

然而,null的存在将被描述作为十亿美元的错误,因此看到诸如TypeScript之类的语言引入修复是令人兴奋的。我强烈建议你把它开着。

解决这个问题的一种方法是确保值永远不是nullundefined,例如通过预先初始化它们:

interface SelectProtected {
readonly wrapperElement: HTMLDivElement;
readonly inputElement: HTMLInputElement;
}


const selectProtected: SelectProtected = {
wrapperElement: document.createElement("div"),
inputElement: document.createElement("input")
};

不过,请参阅瑞安·卡瓦诺的回答以获得替代选项!

如果你从外部知道表达式不是nullundefined,你可以使用非空断言运算符 !强制排除这些类型:

// Error, some.expr may be null or undefined
let x = some.expr.thing;
// OK
let y = some.expr!.thing;

这个解决方案对我很有效:

  • 转到tsconfig.json并添加“strictNullChecks”:假的

enter image description here

更新:对象链接是一种访问可能为空或未定义引用的属性的方法

object?.objectProperty?.nextProperty

以前

if (object !== undefined) {
// continue - error suppressed when used in this way.
}

以前

const objectX = object as string

不过,在选择上述解决方案之前,请考虑您的目标体系结构及其对大局的影响。

这不是OP的问题,但当我意外地将一个形参声明为空类型时,我得到了相同的Object is possibly 'null'消息:

something: null;

而不是给它赋值为null:

something: string = null;

作为一个选项,您可以使用类型强制转换。如果你从typescript中得到这个错误,这意味着某些变量有类型或未定义:

let a: string[] | undefined;


let b: number = a.length; // [ts] Object is possibly 'undefined'
let c: number = (a as string[]).length; // ok

确保a确实存在于你的代码中。

在typescript中,您可以执行以下操作来抑制error:

let subString?: string;

subString > !null; -注意在null之前添加了感叹号。

RxJS的提示

我经常会有类型为Observable<string>的成员变量,直到ngOnInit(使用Angular)才会初始化它。然后编译器假设它是未初始化的,因为它没有“在构造函数中明确赋值”——并且编译器永远不会理解ngOnInit

可以在定义上使用!断言操作符来避免错误:

favoriteColor!: Observable<string>;

未初始化的可观察对象会导致各种运行时错误,比如“你必须提供一个流,但你提供了null”。如果你肯定知道它将被设置在类似ngOnInit的东西中,那么!是可以的,但可能在某些情况下,该值以其他不太确定的方式设置。

所以我有时会使用的替代方法是:

public loaded$: Observable<boolean> = uninitialized('loaded');

其中uninitialized全局定义为:

export const uninitialized = (name: string) => throwError(name + ' not initialized');

然后,如果您使用这个流而没有定义它,它将立即抛出一个运行时错误。

在ReactJS中,我检查构造函数中的变量是否为空,如果为空,我将其视为异常并适当地管理异常。如果变量不为空,代码继续运行,编译器在那之后不再抱怨:

private variable1: any;
private variable2: any;


constructor(props: IProps) {
super(props);


// i.e. here I am trying to access an HTML element
// which might be null if there is a typo in the name
this.variable1 = document.querySelector('element1');
this.variable2 = document.querySelector('element2');


// check if objects are null
if(!this.variable1 || !this.variable2) {
// Manage the 'exception', show the user a message, etc.
} else {
// Interpreter should not complain from this point on
// in any part of the file
this.variable1.disabled = true; // i.e. this line should not show the error
}

当设置状态并使用map时,我用React遇到了这个问题。

在这种情况下,我正在进行API获取调用,响应的值是未知的,但应该有一个值“Answer”。我为此使用了自定义类型,但因为值可以是null,所以我得到了一个TS错误。允许类型为null并不能修复它;或者你可以使用default parameter value,但这对我的情况是混乱的。

我克服了它,通过提供一个默认值,在事件响应是空的,只需使用三元操作符:

this.setState({ record: (response.Answer) ? response.Answer : [{ default: 'default' }] });

如果需要,您可以通过添加注释来抑制(下面请注意)

// @ts-ignore: Object is possibly 'null'.

不是对OP问题的直接回答,但在我的React应用程序中 Typescript - v3.6.2
tslint - v5.20.0

并使用下面的代码

const refToElement = useRef(null);


if (refToElement && refToElement.current) {
refToElement.current.focus(); // Object is possibly 'null' (for refToElement.current)
}

我通过抑制这一行的编译器继续前进

const refToElement = useRef(null);


if (refToElement && refToElement.current) {
// @ts-ignore: Object is possibly 'null'.
refToElement.current.focus();
}

谨慎

请注意,由于这是一个编译器错误而不是linter错误,// tslint:disable-next-line没有工作。此外,根据文档,这应该很少使用,只在必要时使用

更新

在Typescript 3.7以后,你可以使用可选的链接来解决上面的问题

refToElement?.current?.focus();
而且,有时可能只是在使用useRef时将适当的类型传递给泛型参数的问题。
例如:在input元素的情况下-

const refToElement = useRef<HTMLInputElement>(null);

从TypeScript 3.7 (https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-7.html)开始,你现在可以在访问null或未定义对象的属性(或调用方法)时使用?.操作符来获得undefined:

inputEl?.current?.focus(); // skips the call when inputEl or inputEl.current is null or undefined

尝试像这样调用object:

(<any>Object).dosomething

出现此错误是因为您使用?将它们声明为可选。Typescript会做严格的检查,它不允许做任何可能是undefined的事情。因此,你可以在这里使用(<any>yourObject)

要解决这个问题,你可以简单地使用感叹号,如果你确定对象在访问它的属性时不是空的:

list!.values

乍一看,有些人可能会把它与angular中的安全导航操作符混淆,但事实并非如此!

list?.values

!后修正表达式将告诉TS编译器变量不是空,如果不是这样,它将在运行时崩溃

useRef

useRef钩子的用法如下

const value = inputRef?.current?.value

这不是OP的答案,但我看到很多人在评论中对如何避免这个错误感到困惑。这是通过编译器检查的一种简单方法

if (typeof(object) !== 'undefined') {
// your code
}
< p >注意: 这将不起作用

if (object !== undefined) {
// your code
}

这是相当啰嗦的,我不喜欢它,但它是唯一对我有用的东西:

if (inputFile && inputFile.current) {
((inputFile.current as never) as HTMLInputElement).click()
}

只有

if (inputFile && inputFile.current) {
inputFile.current.click() // also with ! or ? didn't work
}

对我没用。Typesript版本:3.9.7,带有eslint和推荐规则。

import React, { useRef, useState } from 'react'
...
const inputRef = useRef()
....
function chooseFile() {
const { current } = inputRef
(current || { click: () => {}}).click()
}
...
<input
onChange={e => {
setFile(e.target.files)
}}
id="select-file"
type="file"
ref={inputRef}
/>
<Button onClick={chooseFile} shadow icon="/upload.svg">
Choose file
</Button>

唯一的代码,对我使用next.js enter image description here < / p >

对我来说,这是一个错误的ref和反应:

const quoteElement = React.useRef()
const somethingElse = quoteElement!.current?.offsetHeight ?? 0

这将抛出错误,修复,给它一个类型:

// <div> reference type
const divRef = React.useRef<HTMLDivElement>(null);


// <button> reference type
const buttonRef = React.useRef<HTMLButtonElement>(null);


// <br /> reference type
const brRef = React.useRef<HTMLBRElement>(null);


// <a> reference type
const linkRef = React.useRef<HTMLLinkElement>(null);

没有错误了,希望这能在某种程度上帮助到其他人,甚至是我自己,P

我在Angular (11.x)中遇到了这个问题。在前一天,我移动了一段HTML/组件到一个单独的-较小的-组件。第二天,我的电脑关机了,我的项目无法构建。 结果是.html组件出了问题。如前所述,这是零安全…

以下(节选):

<div class="code mat-body-strong">\{\{ machine.productCode }}</div>

:

<div class="code mat-body-strong">\{\{ machine?.productCode }}</div>

在typescript中,关闭可能为null的消息:

Interface   {
data: string|null
}


const myData = document.data ?? "";

你可以在以下情况下使用类型强制转换:

// when `textarea` is guaranteed to be loaded
const textarea = <HTMLTextAreaElement>document.querySelector('textarea')
👇 no error here
textarea.value = 'foo'
// @ts-nocheck

将此添加到文件的顶部

enter image description here

很惊讶没有人回答这个问题,你所要做的就是在访问它之前检查对象是否存在,这很直接。否则,请确保在访问对象之前初始化了您的值。

if($protected.listEle.classList) {
$protected.listEle.classList.add('visible');
}

不是OPs问题,但我通过添加一个空检查来解决这个问题

我改变了:

*ngIf="username.invalid &&  username.errors.required"

*ngIf="username.invalid && username.errors != null && username.errors.required"

像这样绑定你的变量variabalName?.value它肯定会工作。

在angular中,我使用:

// eslint-disable-next-line @typescript-eslint/ban-ts-ignore
// @ts-ignore
const sum = row
.filter(p => p.priceInCents !== undefined)
.reduce((sum, current) => sum + current.priceInCents, 0);

因为只是使用@ts-ignore, eslint会抱怨它禁用了编译错误,这就是为什么我添加了eslint-disable-next-line。

与'对象可能为空'编译错误相关,如果你想在typescript配置中禁用这种检查,你应该在tsconfig.json文件中添加下面的行。

"compilerOptions": {


// other rules


"strictNullChecks": false
}
  1. 当我改变"strict:true"“严格:false"在tsconfig。Json文件比代码没有显示错误。

  2. add added !使用添加的obj like进行签名

myImage!.getAttriute('src');

than code isn't showing error.