Tianyi Song

There's no type casting in TypeScript

TL;DR: There’s only type assertion!

An example

Consider this piece of code:

interface X {
    y: number
}

let obj = JSON.parse(`{"a": 1}`);
console.log(obj as X);

This program can successfully compile and run with no report of error. But something is obviously wrong here: the parsed object obj doesn’t have the property y, so “casting” it to type X should fail.

Why?

The as keyword is for type assertion , not type “casting”.

Here, we use the type assertion syntax and tell the compiler that we are sure that obj has type X, so that the rest of the code can type check based on this assumption.

This also applies to other type assertion syntax in TypeScript, like:

let obj: X = JSON.parse(`{"a": 1}`);

This counters my intuition about typed programming languages. In other typed languages, there’s rarely such type assertion. Consider these Java statements:

jshell> Object a = 1;
a ==> 1

jshell> String b = (String) a;
|  Exception java.lang.ClassCastException: class java.lang.Integer cannot be cast to class java.lang.String (java.lang.Integer and java.lang.String are in module java.base of loader 'bootstrap')
|        at (#2:1)

Here, casting an object with the wrong class will throw a ClassCastException. In Golang, unmarshal-ing a JSON object to a struct may also fail.

The Correct Way

The Rule of Thumb is: only use type assertions when you’re sure about it .

If you’re looking for a way to cast an unknown object to a known schema, you might want to check out tools for schema validation, like Yup and Joi .


Edited (17 Oct 2022): Make the article more concise.