Как подавить "ошибку 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?
Ответы
Ответ 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();
}
Подробнее здесь