document.getElementById("id") may be null
Asked Answered
O

5

28

Edit: I'm using TypeScript v2.2.1

I am new to TypeScript and I'm not sure what the cleanest way of dealing with DOM elements that may or may not exist is. Basically, I want to check whether an element exists, and then if it does, add an event listener to it (I have --strict_null_checks turned on).

When I do it the JS-like way:

const myElement = document.getElementById('my-id');
if (myElement) {
  myElement.addEventListener('click', (e:Event) => {
    // Do stuff.
  });
}

I get the error my_script.ts(3, 3): error TS2531: Object is possibly 'null'.

I can get around this by using a not-null assertion:

const maybeMyElement = document.getElementById('my-id');
if (maybeMyElement) {
  const myElement = maybeMyElement!;
  myElement.addEventListener('click', (e:Event) => {
    // Do stuff.
  });
}

But my understanding is that those sorts of assertions are generally frowned upon, and aesthetically, I don't like creating twice as many variables.

Is there a cleaner way to do this?

Overton answered 4/4, 2017 at 22:22 Comment(2)
What version of the Typescript compiler are you using? Your first example works as expected for me (with strictNullChecks on).Bridlewise
Oops, sorry I forgot to mention the version. I'm using version 2.2.1.Overton
C
34

You should type your variables. I haven't done a lot with const, but your second options seems plain wrong (code-smell).

You should be able to get around the warning by strictly typing the variable. The compiler currently sees this as

const myElement: HTMLElement = document.getElementById('my-id');

If you change it to also possibly be null, then nulls are allowed:

const myElement: HTMLElement | null = document.getElementById('my-id');

Updated

Second option (that I haven't tried): use the ! at the end of the potentially null operation, per https://mcmap.net/q/503968/-strictnullchecks-and-getelementbyid

const myElement = document.getElementById('my-id')!;
Clout answered 4/4, 2017 at 22:28 Comment(0)
K
7

Use Optional chaining "?"

Starting TypeScript version 3.7+ you can use Optional Chaining

const maybeMyElement = document.getElementById('my-id');
maybeMyElement?.addEventListener('click', (e: Event) => {
  // Do stuff.
  console.log(e);
});

For older version of TypeScript we would do something like

const maybeMyElement = document.getElementById('my-id') as HTMLElement;
maybeMyElement.addEventListener('click', (e: Event) => {
  // Do stuff.
  console.log(e);
});

Note: Optional chaining (??) is always preferred over non-null assertion operator (!) as non-null assertion can actually lead to run time error if the value comes out to be null or undefined.

And, if you have "plugin:@typescript-eslint/recommended" configured in your eslint settings you will get "Forbidden non-null assertion" warning in your code.

Katelyn answered 1/8, 2020 at 5:22 Comment(1)
Optional Chaining is super clean, thx.Deflected
E
5

Try using the following:

if (!!myElement) {
    myElement.addEventListener('click', (e:Event) => {
        // Do stuff.
    });
}

The !! coerces an object expression into a boolean. It's the ! operator twice. For more info on this, see this answer

Expenditure answered 4/4, 2017 at 22:27 Comment(1)
try editing your answer so I remove the downvote. I inadvertently clicked the downvote button by mistake and can't seem to undo it.Nolin
D
0

if you're using referring to external JS file, then try adding "defer" in your script syntax. eg:

<script src="./script.js" defer></script>
Dregs answered 6/4, 2021 at 13:43 Comment(0)
G
0

ReactJS with Typescript following answer worked for to DOM manipulation

var myModal = document.getElementById('idelement') as HTMLElement;
myModal.getAttribute('style');
Gracie answered 23/5 at 9:43 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.