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
}
