user1151646
user1151646

Reputation:

How to suppress "error TS2533: Object is possibly 'null' or 'undefined'"?

I have a type:

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

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

  maxVisibleListItems?: number
}

I declare a global module-wise variable:

var $protected : tSelectProtected = {};

I'm assigning proper value in function1() scope:

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

Later in function2() scope, I'm calling:

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

I'm getting TypeScript error:

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

I know that I can do explicit check using if ($protected.listEle) {$protected.listEle} to calm down compiler but this seems to be very unhandy for most non trivial cases.

How this situation can or should be handled without disabling TS compiler checks?

Upvotes: 570

Views: 1009273

Answers (30)

Anusha Medicherla
Anusha Medicherla

Reputation: 41

For me , converting to a date seconds, it was throwing the error enter image description here

So converting the date.seconds to a Number type worked:

new Date(Number(date.seconds) * 1000);

Upvotes: 0

Vandesh
Vandesh

Reputation: 6904

Option 1 - Suppressing

You can suppress the compiler error if needed, by adding a comment (with CAUTION below)

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

Not a direct answer to the OP's question, but in my React application with Typescript - v3.6.2
tslint - v5.20.0

And using the following code

const refToElement = useRef(null);

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

I moved on by suppressing the compiler for that line -

const refToElement = useRef(null);

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

CAUTION

Note that since it's a compiler error and not the linter error, // tslint:disable-next-line doesn't work. Also, as per the documentation, this should be used rarely, only when necessary

Option 2 - Optional chaining

With Typescript 3.7 onwards, optional chaining might be applicable in some cases

refToElement?.current?.focus();

But again, only if it's really needed, as in some cases the error might actually point to a bigger problem -

Option 3 - Passing the right type

Also, sometimes it just might be a matter of passing in the appropriate type to the generic paramenter, while using useRef.
Eg: In case of an input element -

const refToElement = useRef<HTMLInputElement>(null);

Upvotes: 103

Naved Khan
Naved Khan

Reputation: 1

this can also be resolved using -> optional chaining (?.) operator for example :

<h2>Price : {{productDetail?.productPrice}}</h2>

if the object 'productDetail' is possible undefined .

Upvotes: 0

Ahmad Khudeish
Ahmad Khudeish

Reputation: 1137

Pretty surprised no one answered this, all you got to do is check if the object exists before accessing it, it's pretty straight forward. Otherwise, make sure you initialize the values that your before accessing the object.

if($protected.listEle.classList) {
   $protected.listEle.classList.add('visible');
}

Upvotes: 2

Mudassar Mustafai
Mudassar Mustafai

Reputation: 118

  1. When I changed "strict:true" to "strict:false" in tsconfig.json file than code isn't showing error.

  2. add added ! sign with obj like added

    myImage!.getAttriute('src');
    

than code isn't showing error.

Upvotes: 4

Duck Ling
Duck Ling

Reputation: 2160

Note: it might not be a recommended action - maybe the solution is to actually address the errors. All the checks are in place for a reason, so disabling them is not always the right thing to do, but...

a similar answer to some of the above, but a little bit different in the end. I've had an issue with multiple different checks and what helped me was setting a strict property to false in tsconfig.json. Seems like a more generic variation of the specific checks mentioned above.

  "compilerOptions": {
    "strict": false
  },

Upvotes: 1

Wenfang Du
Wenfang Du

Reputation: 11417

You can use type casting for situations like:

// when `textarea` is guaranteed to be loaded
const textarea = <HTMLTextAreaElement>document.querySelector('textarea')
šŸ‘‡ no error here
textarea.value = 'foo'

Upvotes: 3

Ryan Cavanaugh
Ryan Cavanaugh

Reputation: 221332

If you know from external means that an expression is not null or undefined, you can use the non-null assertion operator ! to coerce away those types:

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

Upvotes: 1200

Mehdi Roostaeian
Mehdi Roostaeian

Reputation: 521

Related to 'object is possibly null' compile error, if you want to disable this checking in your typescript configuration, you should add the below line in the tsconfig.json file.

"compilerOptions": {

   // other rules

   "strictNullChecks": false
}

Upvotes: 14

Shmarkus
Shmarkus

Reputation: 188

In angular, I use:

// 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);

Since just using @ts-ignore, the eslint complains that it disables compilation errors, this is why I add the eslint-disable-next-line.

Upvotes: 1

Vibhu kumar
Vibhu kumar

Reputation: 396

Bind you variable like this variabalName?.value It will work for sure.

Upvotes: 2

Nick
Nick

Reputation: 3347

Not OPs problems but I fixed this by adding a null check

I changed:

*ngIf="username.invalid &&  username.errors.required"

To

*ngIf="username.invalid && username.errors != null && username.errors.required"

Upvotes: 1

JoshuaTree
JoshuaTree

Reputation: 1261

Update: Object chaining is a means to access properties on possibly null or undefined reference

object?.objectProperty?.nextProperty

Previously

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

Previously

const objectX = object as string

Although, before choosing one of the above workarounds, please consider the architecture you are aiming for and it's impact to the bigger picture.

Upvotes: 59

dawid debinski
dawid debinski

Reputation: 540

In typescript, to mute message about possibility null:

Interface   {
  data: string|null
}

const myData = document.data ?? "";

Upvotes: 0

Jamie Hutber
Jamie Hutber

Reputation: 28106

For me this was an error with the ref and react:

const quoteElement = React.useRef()
const somethingElse = quoteElement!.current?.offsetHeight ?? 0

This would throw the error, the fix, to give it a type:

// <div> reference type
const divRef = React.useRef<HTMLDivElement>(null);

// <button> reference type
const buttonRef = React.useRef<HTMLButtonElement>(null);

// <br /> reference type
const brRef = React.useRef<HTMLBRElement>(null);

// <a> reference type
const linkRef = React.useRef<HTMLLinkElement>(null);

No more errors, hopefully in some way this might help somebody else, or even me in the future :P

Upvotes: 9

O-9
O-9

Reputation: 1779

I had this problem with Angular (11.x). On a previous day I moved a piece of HTML/component to a individual - smaller - component. On the next day my computer had shut down and my project couldn't build. It turned out that the component .html was the problem. So as said, it's the null safety...

From this (excerpt):

<div class="code mat-body-strong">{{ machine.productCode }}</div>

To this:

<div class="code mat-body-strong">{{ machine?.productCode }}</div>

Upvotes: 0

Emanuel
Emanuel

Reputation: 3277

import React, { useRef, useState } from 'react'
...
const inputRef = useRef()
....
function chooseFile() {
  const { current } = inputRef
  (current || { click: () => {}}).click()
}
...
<input
   onChange={e => {
     setFile(e.target.files)
    }}
   id="select-file"
   type="file"
   ref={inputRef}
/>
<Button onClick={chooseFile} shadow icon="/upload.svg">
   Choose file
</Button>

the unique code that works to me using next.js enter image description here

Upvotes: 0

Ericgit
Ericgit

Reputation: 7103

To fix this you can simply use the exclamation mark if you're sure that the object is not null when accessing its property:

list!.values

At first sight, some people might confuse this with the safe navigation operator from angular, this is not the case!

list?.values

The ! post-fix expression will tell the TS compiler that variable is not null, if that's not the case it will crash at runtime

useRef

for useRef hook use like this

const value = inputRef?.current?.value

Upvotes: 36

mosu
mosu

Reputation: 587

This is rather verbose and don't like it but it's the only thing that worked for me:

if (inputFile && inputFile.current) {
        ((inputFile.current as never) as HTMLInputElement).click()
}

only

if (inputFile && inputFile.current) {
        inputFile.current.click() // also with ! or ? didn't work
}

didn't work for me. Typesript version: 3.9.7 with eslint and recommended rules.

Upvotes: 2

Douglas
Douglas

Reputation: 37781

This feature is called "strict null checks", to turn it off ensure that the --strictNullChecks compiler flag is not set.

However, the existence of null has been described as The Billion Dollar Mistake, so it is exciting to see languages such as TypeScript introducing a fix. I'd strongly recommend keeping it turned on.

One way to fix this is to ensure that the values are never null or undefined, for example by initialising them up front:

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

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

See Ryan Cavanaugh's answer for an alternative option, though!

Upvotes: 199

Joe
Joe

Reputation: 23

This is not an answer for the OP but I've seen a lot of people confused about how to avoid this error in the comments. This is a simple way to pass the compiler check

if (typeof(object) !== 'undefined') {
    // your code
}

Note: This won't work

if (object !== undefined) {
        // your code
    }

Upvotes: 1

Ankita Srivastava
Ankita Srivastava

Reputation: 39

Try to call object like this:

(<any>Object).dosomething

This error has come because you have declared them as optional using ?. Now Typescript does strict check and it won't allow doing anything that may be undefined. Therefore, you can use (<any>yourObject) here.

Upvotes: 2

Jonathan Cast CONT
Jonathan Cast CONT

Reputation: 51

As of TypeScript 3.7 (https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-7.html), you can now use the ?. operator to get undefined when accessing an attribute (or calling a method) on a null or undefined object:

inputEl?.current?.focus(); // skips the call when inputEl or inputEl.current is null or undefined

Upvotes: 5

Chris Shaffer
Chris Shaffer

Reputation: 66

I ran in to this with React when setting state and using map.

In this case I was making an API fetch call and the value of the response wasn't known, but should have a value "Answer". I used a custom type for this, but because the value could be null, I got a TS error anyway. Allowing the type to be null doesn't fix it; alternatively you could use a default parameter value, but this was messy for my case.

I overcame it by providing a default value in the event the response was empty by just using a ternary operator:

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

Upvotes: 3

Gideon
Gideon

Reputation: 1068

In ReactJS, I check in the constructor if the variables are null, if they are I treat it like an exception and manage the exception appropriately. If the variables are not null, code carries on and compiler does not complain anymore after that point:

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
    }

Upvotes: 5

Simon_Weaver
Simon_Weaver

Reputation: 146188

Tip for RxJS

I'll often have member variables of type Observable<string>, and I won't be initializing it until ngOnInit (using Angular). The compiler then assumes it to be uninitialized becasue it isn't 'definitely assigned in the constructor' - and the compiler is never going to understand ngOnInit.

You can use the ! assertion operator on the definition to avoid the error:

favoriteColor!: Observable<string>;

An uninitialized observable can cause all kinds of runtime pain with errors like 'you must provide a stream but you provided null'. The ! is fine if you definitely know it's going to be set in something like ngOnInit, but there may be cases where the value is set in some other less deterministic way.

So an alternative I'll sometimes use is :

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

Where uninitialized is defined globally somewhere as:

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

Then if you ever use this stream without it being defined it will immediately throw a runtime error.

Upvotes: 5

user3834142
user3834142

Reputation: 561

In typescript you can do the following to suppress the error:

let subString?: string;

subString > !null; - Note the added exclamation mark before null.

Upvotes: 2

Shevchenko Viktor
Shevchenko Viktor

Reputation: 5406

As an option, you can use a type casting. If you have this error from typescript that means that some variable has type or is undefined:

let a: string[] | undefined;

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

Be sure that a really exist in your code.

Upvotes: 14

thinkOfaNumber
thinkOfaNumber

Reputation: 2883

This is not the OP's problem, but I got the same Object is possibly 'null' message when I had declared a parameter as the null type by accident:

something: null;

instead of assigning it the value of null:

something: string = null;

Upvotes: 17

Mahesh Nepal
Mahesh Nepal

Reputation: 1439

This solution worked for me:

  • go to tsconfig.json and add "strictNullChecks":false

enter image description here

Upvotes: 76

Related Questions