我有一个类型:

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进行显式检查。listEle}使编译器平静下来,但这似乎对于大多数非平凡的情况非常不方便。

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


当前回答

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

// @ts-ignore:对象可能是空的。

不是对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时将适当的类型传递给泛型参数的问题。 在输入元素的情况下-

const refToElement = useRef<HTMLInputElement>(null);

其他回答

如果您从外部知道表达式不是空或未定义的,则可以使用非空断言操作符!为了赶走这些类型:

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

这个特性被称为“strict null checks”,关闭它时要确保没有设置编译器标志——strictNullChecks。

然而,null的存在被描述为“十亿美元的错误”,所以看到像TypeScript这样的语言引入修复是令人兴奋的。我强烈建议你把它开着。

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

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

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

不过,请参阅Ryan Cavanaugh的另一种选择的答案!

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

let a: string[] | undefined;

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

确保代码中确实存在a。

在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。

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