24

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?

Evan Hefner
  • 347
  • 1
  • 2
  • 5
  • What version of the Typescript compiler are you using? Your first example works as expected for me (with `strictNullChecks` on). – y2bd Apr 04 '17 at 23:21
  • Oops, sorry I forgot to mention the version. I'm using version 2.2.1. – Evan Hefner Apr 05 '17 at 19:53

4 Answers4

29

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://stackoverflow.com/a/40640854/2084315

const myElement = document.getElementById('my-id')!;
Community
  • 1
  • 1
ps2goat
  • 7,677
  • 1
  • 31
  • 66
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

  • try editing your answer so I remove the downvote. I inadvertently clicked the downvote button by mistake and can't seem to undo it. – abidmix Oct 27 '17 at 20:17
5

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);
});
Vandesh
  • 5,508
  • 1
  • 24
  • 31
1

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

<script src="./script.js" defer></script>
Tomerikoo
  • 15,737
  • 15
  • 35
  • 52