Type Assertion
TypeScript allows you to override its inferred and analyzed view of types in any way you want to. This is done by a mechanism called "type assertion". TypeScript's type assertion is purely you telling the compiler that you know about the types better than it does, and that it should not second guess you.
A common use case for type assertion is when you are porting over code from JavaScript to TypeScript. For example consider the following pattern:
Here the code errors because the inferred type of foo
is {}
i.e. an object with zero properties. Therefore you are not allowed to add bar
or bas
to it. You can fix this simply by a type assertion as Foo
:
as foo
vs. <foo>
as foo
vs. <foo>
Originally the syntax that was added was <foo>
. This is demonstrated below:
However, there is an ambiguity in the language grammar when using <foo>
style assertions in JSX:
Therefore it is now recommended that you just use as foo
for consistency.
Type Assertion vs. Casting
The reason why it's not called "type casting" is that casting generally implies some sort of runtime support. However, type assertions are purely a compile time construct and a way for you to provide hints to the compiler on how you want your code to be analyzed.
Assertion considered harmful
In many cases assertion will allow you to easily migrate legacy code (and even copy paste other code samples into your codebase). However, you should be careful with your use of assertions. Take our original code as a sample, the compiler will not protect you from forgetting to actually add the properties you promised:
Also another common thought is using an assertion as a means of providing autocomplete e.g.:
but the hazard here is the same, if you forget a property the compiler will not complain. It is better if you do the following:
In some cases you might need to create a temporary variable, but at least you will not be making (possibly false) promises and instead relying on the type inference to do the checking for you.
Double assertion
The type assertion, despite being a bit unsafe as we've shown, is not completely open season. E.g. the following is a very valid use case (e.g. the user thinks the event passed in will be a more specific case of an event) and the type assertion works as expected:
However, the following is most likely an error and TypeScript will complain as shown despite the user's type assertion:
If you still want that Type, you can use a double assertion, but first asserting to any
which is compatible with all types and therefore the compiler no longer complains:
How TypeScript determines if a single assertion is not enough
Basically, the assertion from type S
to T
succeeds if either S
is a subtype of T
or T
is a subtype of S
. This is to provide extra safety when doing type assertions ... completely wild assertions can be very unsafe and you need to use any
to be that unsafe.
Last updated