Подтвердить что ты не робот

Как подавить "ошибку TS2533: объект может быть" нулевым "или" неопределенным ""?

У меня есть 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?

4b9b3361

Ответ 1

Эта функция называется "строгие проверки на ноль", чтобы ее отключить, убедитесь, что флаг компилятора --strictNullChecks не установлен.

Однако существование null было описано как ошибка в миллиардный доллар, поэтому интересно видеть, что такие языки, как TypeScript, вводят исправление. Я настоятельно рекомендую держать его включенным.

Один из способов исправить это - убедиться, что значения никогда не равны null или undefined, например, предварительно инициализируя их:

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

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

См. ответ райана Кавано для альтернативного варианта!

Ответ 2

Если вы знаете из внешних средств, что выражение не является null или undefined, вы можете использовать оператор ненулевого утверждения ! для принудительного удаления этих типов:

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

Ответ 3

Я использовал:

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

В качестве альтернативы вы можете использовать приведение типа:

const objectX = object as string

Хотя, прежде чем выбрать один из вышеперечисленных обходных путей, рассмотрите архитектуру, к которой вы стремитесь, и это повлияет на общую картину.

Ответ 4

Если вы знаете, что тип никогда не будет null или undefined, вы должны объявить его как foo: Bar без ?. Объявление типа с синтаксисом ? Bar означает, что он потенциально может быть undefined, что вам нужно проверить.

Другими словами, компилятор делает именно то, о чем вы просите. Если вы хотите, чтобы он был необязательным, вам нужно проверить его позже.

Ответ 5

Это решение сработало для меня:

  • перейдите к tsconfig.json и добавьте "strictNullChecks": false

enter image description here

Ответ 6

Это не проблема OP, но я получил тот же Object is possibly 'null' сообщение, когда я случайно объявил параметр как нулевой тип:

something: null;

вместо присвоения ему значения null:

something: string = null;

Ответ 7

Как вариант, вы можете использовать приведение типов. Если у вас есть эта ошибка из машинописного текста, это означает, что некоторая переменная имеет тип или не определена:

let a: string[] | undefined;

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

Убедитесь, что действительно существуют в вашем коде. a

Ответ 8

В ReactJS я проверяю в конструкторе, являются ли переменные нулевыми, если они есть, я рассматриваю это как исключение и соответствующим образом управляю этим исключением. Если переменные не равны 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
    }

Ответ 9

Совет для RxJS

У меня часто будут переменные-члены типа Observable<string>, и я не буду инициализировать их до ngOnInit (используя Angular). Затем компилятор предполагает, что он неинициализирован, потому что он не "определенно назначен в конструкторе" - и компилятор никогда не поймет ngOnInit.

Вы можете использовать ! утверждение оператора на определение, чтобы избежать ошибки:

favoriteColor!: Observable<string>;

Неинициализированная наблюдаемая может вызвать все виды проблем во время выполнения с ошибками типа "вы должны предоставить поток, но вы предоставили ноль". ! Это хорошо, если вы точно знаете, что он будет установлен в нечто вроде ngOnInit, но могут быть случаи, когда значение устанавливается каким-то другим, менее детерминированным способом.

Поэтому я иногда использую альтернативу:

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

Где uninitialized определяется глобально где-то как:

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

Тогда, если вы когда-либо будете использовать этот поток без его определения, он немедленно выдаст ошибку времени выполнения.

Ответ 10

Я столкнулся с этим с React при установке состояния и использовании map.

В этом случае я делал вызов извлечения API, и значение ответа не было известно, но должно иметь значение "Ответ". Я использовал для этого пользовательский тип, но поскольку значение могло быть null, я все равно получил ошибку TS. Разрешение типа быть null не исправляет его; В качестве альтернативы вы можете использовать default parameter value, но это было грязно для моего случая.

Я преодолел это, предоставив значение по умолчанию в случае, если ответ был пустым, просто используя троичный оператор:

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

Ответ 11

Не прямой ответ на вопрос ОП, но в моем случае у меня была следующая настройка -

Машинопись - v3.6.2
Цлинт - v5.20.0

И используя следующий код

const refToElement = useRef(null);

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

Я пошел дальше, подавив компилятор для этой строки. Обратите внимание, что, поскольку это ошибка компилятора, а не ошибки линтера, // tslint:disable-next-line не работал. Кроме того, в соответствии с документацией, это следует использовать редко, только при необходимости -

const refToElement = useRef(null);

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

Ответ 12

В машинописи вы можете сделать следующее, чтобы подавить error:

let subString?: string;

subString > !null; - Обратите внимание на добавленный восклицательный знак перед нулем.

Ответ 13

Если у вас есть эта проблема с ссылками в React, строгих проверок на ноль должно быть достаточно:

if (inputEl && inputEl.current) {
     inputEl.current.focus();
}

Подробнее здесь