Pesquisa de site

typescript - Como suprimir "erro TS2533: O objeto pode ser 'null' ou 'undefined'?"


Eu tenho um tipo:

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

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

  maxVisibleListItems?: number
}

Eu declaro uma variável global por módulo:

var $protected : tSelectProtected = {};

Estou atribuindo o valor adequado no escopo de function1():

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

Mais tarde, no escopo de function2(), estou chamando:

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

Estou recebendo um erro de TypeScript:

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

Eu sei que posso fazer uma verificação explícita usando if ($protected.listEle) {$protected.listEle} para acalmar o compilador, mas isso parece ser muito inconveniente para a maioria dos casos não triviais.

Como essa situação pode ou deve ser tratada sem desativar as verificações do compilador TS?

Resposta #1

Se você souber por meios externos que uma expressão não é null ou undefined, você pode usar o operador de afirmação de não-nulo ! para eliminar esses tipos:

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

Resposta #2

Esse recurso é chamado de "verificações nulas rigorosas", para desativá-lo, certifique-se de que a flag do compilador --strictNullChecks não esteja definida.

No entanto, a existência de null foi descrita como O Erro de Um Bilhão de Dólares, então é empolgante ver linguagens como TypeScript introduzindo uma correção. Eu recomendaria fortemente mantê-lo ativado.

Uma maneira de corrigir isso é garantir que os valores nunca sejam null ou undefined, por exemplo, inicializando-os desde o início:

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

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

Veja a resposta de Ryan Cavanaugh para uma opção alternativa, entretanto!

Resposta #3

Opção 1 - Suprimindo

Você pode suprimir o erro do compilador, se necessário, adicionando um comentário (com CUIDADO abaixo)

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

Não é uma resposta direta à pergunta do OP, mas no meu aplicativo React com Typescript - v3.6.2
tslint - v5.20.0

E usando o seguinte código

const refToElement = useRef(null);

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

Eu segui em frente suprimindo o compilador para aquela linha -

const refToElement = useRef(null);

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

CUIDADO

Observe que, como é um erro de compilador e não um erro do linter, // tslint:disable-next-line não funciona. Além disso, conforme a documentação, isso deve ser usado raramente, apenas quando necessário

Opção 2 - Encadeamento opcional

A partir do TypeScript 3.7, o encadeamento opcional pode ser aplicável em alguns casos

refToElement?.current?.focus();

Mas, novamente, somente se for realmente necessário, pois em alguns casos o erro pode realmente indicar um problema maior -

Opção 3 - Passando o tipo correto

Além disso, às vezes pode ser apenas uma questão de passar o tipo apropriado para o parâmetro genérico, ao usar useRef.
Por exemplo: no caso de um elemento input -

const refToElement = useRef<HTMLInputElement>(null);

Resposta #4

Esta solução funcionou para mim:

  • vá para tsconfig.json e adicione "strictNullChecks":false

Resposta #5

Atualização: O encadeamento de objetos é um meio de acessar propriedades em uma referência possivelmente nula ou indefinida

object?.objectProperty?.nextProperty

Anteriormente

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

Anteriormente

const objectX = object as string

Embora, antes de escolher uma das soluções alternativas acima, por favor, considere a arquitetura que você está buscando e seu impacto no panorama geral.

Resposta #6

Para corrigir isso, você pode simplesmente usar o ponto de exclamação se tiver certeza de que o objeto não é nulo ao acessar sua propriedade:

list!.values

À primeira vista, algumas pessoas podem confundir isso com o operador de navegação segura do Angular, mas esse não é o caso!

list?.values

A expressão pós-fixada ! dirá ao compilador TS que a variável não é nula, se esse não for o caso, ela irá travar em tempo de execução

useRef

para o hook useRef use assim

const value = inputRef?.current?.value

Resposta #7

Se você sabe que o tipo nunca será null ou undefined, você deve declará-lo como foo: Bar sem o ?. Declarar um tipo com a sintaxe ? Bar significa que ele potencialmente poderia ser undefined, algo que você precisa verificar.

Em outras palavras, o compilador está fazendo exatamente o que você está pedindo. Se você quiser que seja opcional, precisará verificar mais tarde.

Resposta #8

Este não é o problema do OP, mas eu recebi a mesma mensagem Object is possibly 'null' quando declarei um parâmetro como do tipo nulo por acidente:

something: null;

em vez de atribuir a ele o valor nulo:

something: string = null;

Resposta #9

Como opção, você pode usar uma conversão de tipo. Se você tem esse erro do TypeScript, isso significa que alguma variável tem tipo ou está indefinida:

let a: string[] | undefined;

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

Certifique-se de que a realmente existe no seu código.

Resposta #10

Relacionado ao erro de compilação 'object is possibly null', se você quiser desativar essa verificação na sua configuração do TypeScript, você deve adicionar a linha abaixo no arquivo tsconfig.json.

"compilerOptions": {

   // other rules

   "strictNullChecks": false
}

Artigos relacionados