When working with TypeScript in the browser, I often find myself writing code like this:
const button = document.getElementById(id);
if (!(button instanceof HTMLButtonElement)) {
throw new Error("TODO -- insert better error message here");
}
button.disabled = false;
The throw
statement is necessary because getElementById() returns type HTMLElement | null
, which doesn't support the disabled property. After the throw
, the type changes to HTMLButtonElement
. While I could use a type assertion, I prefer including a runtime check in this code.
I wonder if there's a way to encapsulate this logic in a function, such as:
const button = verify(document.getElementById(id), HTMLButtonElement);
button.disabled = false;
or
const button = verify<HTMLButtonElement>(document.getElementById(id));
button.disabled = false;
But not like:
const button = verify<HTMLButtonElement>(document.getElementById(id), HTMLButtonElement);
button.disabled = false;
because that would involve repeating the same word and lead to potential mistakes.
In languages like Java or C#, I would use
(HTMLButtonElement)document.getElementById(id)
instead of verify()
. In C++, it might be something like dynamic_cast< HTMLButtonElement & >(document.getElementById(id))
. Essentially, I'm looking to perform the runtime check while also satisfying the compiler, all while minimizing unnecessary typing.