How to get type of object in TypeScript, when using union types and type guards for multiple types of function parameter or variable.

May 27, 2015

tl;dr

When checking for primitive types in TypeScript , typeof variable === “string” or typeof variable === “number” should do the job.

When checking for HTMLElement or HTMLDivElement type of objects, variable instanceof HTMLElement or variable instanceof HTMLDivElement type of check should be the right one.

Please note that this is somewhat simplified point of view. I was only using simple objects and elements from one page. If you will run into some specialties, please read this article : http://perfectionkills.com/instanceof-considered-harmful-or-how-to-write-a-robust-isarray/ and write as much unit tests as possible for you scenario. There might be some scenario where using typeof and instanceof are simple not enough.

The whole story :

My beloved TypeScript 1.4 we got a while back came with a new lovely possibility of having parameters passed as object that might be of several different types. For example you can accept either string or array of strings, where if passed a plain string, you can split it and continue with array of strings or use directly passed array.

We can argue if this is a good and clean solution from architectural point of view, but if for whatever reason this will be a requirement how the function should work, than we can leverage two sweet features of TypeScript :

Both might be used also separately or with some plain var in your code (you can just define var that will be of types string | HTMLElement | number) but if used together, Type Guards are building on top of Union Types feature and giving you some sweet stuff.

So what you get is, that TypeScript now understands what are you doing, when you check for one of types that variable might be of and you can get IntelliSense for that type (I am little fast forwarding here to the function I want to show you but this is what I mean by that) :

param check intellisense

And here I am getting to the main point of this particle and that is : how can we check for HTML elements of any other object from the DOM world?

As you all know, getting the basic types in JavaScript if quite difficult if you run into edge cases or the type you check for might be also array or stuff like that. You can read great article like this one : http://stackoverflow.com/questions/332422/how-do-i-get-the-name-of-an-objects-type-in-javascript. There are many caveats. 🙁

typeof will do, for the most part :

But most of the time, for basic types we are OK with using typeof operator and comparing against “string” or “number” but what about HTMLElement or HTMLDivElement object in TypeScript? Do the exist in the vast and wild JavaScript world? Yes the do exist, but dependent on the browser age with different results. Another misleading thing is that unfortunately the typeof operator will not work we want for HTMLElement and similar types of objects, but neither will the approach create an error, because every time we would get string “object” which is OK from inheritance point of view but its not what we need.

instanceof to the rescue :

What will work here is instanceof operator. Nice article also here : https://stackoverflow.com/questions/46703364/why-does-instanceof-in-typescript-give-me-the-error-foo-only-refers-to-a-ty. Again, there are some caveats here (like this http://stackoverflow.com/questions/472418/why-is-4-not-an-instance-of-number) when used with primitive types like string, so I advice you to stick with instanceof for instances of objects or for checking of types from the DOM side of the world.

The snippet :

And here it is ladies and gentleman, the glamorous sample snippet I wanted to share with you (for testing purposes):

export function parCheckDemo(param: string | number | HTMLElement | HTMLImageElement | HTMLDivElement): void {
    if (param instanceof HTMLDivElement) {
        console.log(‘HTMLDivElement’);
    } else if (param instanceof HTMLImageElement) {
        console.log(‘HTMLImageElement’);
    } else if (param instanceof HTMLElement) {
        console.log(‘HTMLElement’);
    } else if (typeof param === “string”) {
        console.log(‘string’);
    } else if (typeof param === “number”) {
        console.log(‘number’);
    } else {
        console.log(“You’re not supposed to be here! – Levelord”);
    }
}

Hope this helps dear reader, enjoy. If you have any suggestions to the code, please feel free to share in the comments.

PS: yes, in real life I (and you too) should probably first check if anyone passed something as param argument , this snippet is jut for demo purposes.

Hope this helps.


Profile picture

Written by Dušan Roštár - the "mr edge case" guy
my twitter : rostacik, my linkedin : rostar, drop me an email : here