我有一个类型:
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编译器检查的情况下处理这种情况?
答案 0 :(得分:371)
如果从外部知道表达式不是null
或undefined
,则可以使用非空断言运算符!
来强制转换这些类型:
// Error, some.expr may be null or undefined
let x = some.expr.thing;
// OK
let y = some.expr!.thing;
答案 1 :(得分:42)
此功能称为“严格空检查”,将其关闭以确保未设置--strictNullChecks
编译器标志。
但是,null
的存在时been described为The Billion Dollar Mistake,因此看到TypeScript等语言引入修复程序令人兴奋。我强烈建议保持打开状态。
解决此问题的一种方法是确保值永远不会是null
或undefined
,例如通过预先初始化它们:
interface SelectProtected {
readonly wrapperElement: HTMLDivElement;
readonly inputElement: HTMLInputElement;
}
const selectProtected: SelectProtected = {
wrapperElement: document.createElement("div"),
inputElement: document.createElement("input")
};
答案 2 :(得分:16)
我用过:
Resource leak: 'context' is never closed
或者,您可以使用类型强制:
if (object !== undefined) {
// continue - error suppressed when used in this way.
}
虽然在选择上述解决方法之一之前,请考虑您的目标架构,并对整体情况产生影响。
答案 3 :(得分:14)
要解决此问题,如果在访问对象的属性时确定该对象不为null,则只需使用感叹号即可:
eatableFillColor(id)
{
if (some_condition)
{
return "white";
}
return "black";
}
乍一看,有些人可能会把它与安全的导航操作员从角度上混淆,事实并非如此!
const MyCom = () => {
//do something here. ex, open gallery to upload image, zoon in image in
useEffect(() => {
// Component Did Mount
return => {
// ComponentWillUnmount
}
},[])
return(/*Component*/)
}
list!.values
后缀表达式将告诉TS编译器变量不为null,否则变量将在运行时崩溃
用于list?.values
钩子这样使用
!
答案 4 :(得分:9)
如果您知道该类型永远不会是a()
或null
,则应在没有undefined
的情况下将其声明为foo: Bar
。声明具有?
语法的类型意味着它可能未定义,这是您需要检查的内容。
换句话说,编译器正在完全按照您的要求进行操作。如果您希望它是可选的,您需要稍后检查。
答案 5 :(得分:6)
答案 6 :(得分:6)
这不是OP的问题,但是当我偶然将参数声明为null类型时,我得到了相同的Object is possibly 'null'
消息:
something: null;
而不是为其赋值null:
something: string = null;
答案 7 :(得分:4)
您可以选择使用类型转换。如果您在打字稿中遇到此错误,则意味着某些变量具有类型或未定义:
let a: string[] | undefined;
let b: number = a.length; // [ts] Object is possibly 'undefined'
let c: number = (a as string[]).length; // ok
请确保您的代码中确实存在a
。
答案 8 :(得分:4)
不是OP的问题的直接答案,但就我而言,我具有以下设置-
打字稿-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)
}
我继续取消了该行的编译器。请注意,由于这是编译器错误,而不是linter错误,因此// tslint:disable-next-line
不起作用。另外,as per the documentation, this should be used rarely, only when necessary-
const refToElement = useRef(null);
if (refToElement && refToElement.current) {
// @ts-ignore: Object is possibly 'null'.
refToElement.current.focus();
}
答案 9 :(得分:1)
从TypeScript 3.7(https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-7.html开始,现在您可以使用public class Video {
private FFmpegFrameGrabber grabber;
private final static Java2DFrameConverter converter = new Java2DFrameConverter();
public Video(File file) {
this.grabber = new FFmpegFrameGrabber(file);
try {
this.grabber.start();
} catch (Exception e) {
e.printStackTrace();
}
}
public BufferedImage grabFrame(int framePos) throws Exception {
BufferedImage frame;
grabber.grabImage(); // Without this done before, the image is just black
grabber.setFrameNumber(framePos);
frame = converter.convert(grabber.grabImage());
return frame;
}
}
运算符在访问null或未定义对象上的属性(或调用方法)时得到未定义:
?.
答案 10 :(得分:1)
这不是OP的答案,但我看到很多人对如何避免注释中的错误感到困惑。这是通过编译器检查的简单方法
if (typeof(object) !== 'undefined') {
// your code
}
注意: 这是行不通的
if (object !== undefined) {
// your code
}
答案 11 :(得分:1)
尝试这样调用对象:
(<any>Object).dosomething
之所以出现此错误,是因为您已使用?
将它们声明为可选的。现在,Typescript会进行严格检查,并且不允许做任何可能undefined
的事情。因此,您可以在此处使用(<any>yourObject)
。
答案 12 :(得分:1)
在ReactJS中,我检查构造函数中的变量是否为null,是否将它们视为异常,并适当地管理该异常。如果变量不为null,则代码会继续执行,并且编译器在此之后不再发出错误消息:
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
}
答案 13 :(得分:0)
如果您在React中使用refs遇到此问题,则严格的null检查就足够了:
if (inputEl && inputEl.current) {
inputEl.current.focus();
}
更多here
答案 14 :(得分:0)
设置状态并使用map
时,我用React遇到了这个问题。
在这种情况下,我正在进行API提取调用,并且响应的值未知,但是应该的值为“ Answer”。我为此使用了自定义类型,但是由于该值可能为null
,所以我还是遇到了TS错误。允许类型为null
并不能解决问题;或者,您可以使用default parameter value
,但这对我来说很麻烦。
在仅使用三元运算符的情况下响应为空的情况下,我通过提供默认值来克服它:
this.setState({ record: (response.Answer) ? response.Answer : [{ default: 'default' }] });
答案 15 :(得分:0)
我经常会有类型为Observable<string>
的成员变量,并且直到ngOnInit
(使用Angular)之前我都不会对其进行初始化。然后,编译器会认为它是未初始化的,因为它没有“在构造函数中明确分配”-并且编译器永远不会理解ngOnInit
。
您可以在定义中使用!
断言运算符来避免错误:
favoriteColor!: Observable<string>;
未初始化的observable可能导致各种运行时痛苦,并出现诸如“您必须提供流但您提供null”之类的错误。如果您肯定地知道将以!
之类的方式进行设置,那么ngOnInit
很好,但是在某些情况下,该值可以通过其他一些不确定性的方式来设置。
所以我有时会使用的替代方法是:
public loaded$: Observable<boolean> = uninitialized('loaded');
uninitialized
全局定义为:
export const uninitialized = (name: string) => throwError(name + ' not initialized');
然后,如果您在未定义此流的情况下使用此流,它将立即引发运行时错误。
答案 16 :(得分:0)
在打字稿中,您可以执行以下操作以禁止显示error
:
let subString?: string;
subString > !null;
-注意在null之前添加的感叹号。
答案 17 :(得分:0)
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>
答案 18 :(得分:0)
对我来说,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
答案 19 :(得分:0)
我在使用 Angular (11.x) 时遇到了这个问题。在前一天,我将一段 HTML/组件移到了一个单独的(较小的)组件中。第二天,我的电脑关机了,我的项目无法构建。 事实证明,组件 .html 是问题所在。如前所述,这是零安全...
从此(摘录):
<div class="code mat-body-strong">{{ machine.productCode }}</div>
为此:
<div class="code mat-body-strong">{{ machine?.productCode }}</div>
答案 20 :(得分:0)
在打字稿中,将有关可能性为 null 的消息静音:
Interface {
data: string|null
}
const myData = document.data ?? "";
答案 21 :(得分:0)
您可以在以下情况下使用类型转换:
// `textarea` is guaranteed to be loaded
const textarea = <HTMLTextAreaElement>document.querySelector('textarea')
? no error here
textarea.value = 'foo'
答案 22 :(得分:0)
答案 23 :(得分:0)
很惊讶没有人回答这个问题,您所要做的就是在访问对象之前检查对象是否存在,这非常简单。否则,请确保在访问对象之前初始化您的值。
if($protected.listEle.classList) {
$protected.listEle.classList.add('visible');
}
答案 24 :(得分:0)
不是 OP 问题,但我通过添加空检查解决了这个问题
我改变了:
*ngIf="username.invalid && username.errors.required"
到
*ngIf="username.invalid && username.errors != null && username.errors.required"
答案 25 :(得分:0)
像这样绑定你的变量 variabalName?.value
它肯定会起作用。
答案 26 :(得分:0)
在角度,我使用:
// 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 的原因。