Type Annotations In Action
Type Annotations and Type Inference
A type annotation is an explicit bit of code that tells TypeScript what type of value some variable refers to.
In contrast, type inference tries to figure out the type for that variable for you.
The question for the developer is: when should you explicitly type a variable using type annotation, and when should you rely on type inference?
Type Annotations
Annotating variables
To type annotate a variable, just do this:
Annotating objects
To annotate more complex object types, just do this:
Annotating functions
To annotate a function, just do this:
Note: (i: number) => void
is the syntax for type annotating a variable storing a function. (You'll learn how to annotate a function itself later.) The left-hand side tells TypeScript the types for the arguments, while the right-hand side tells TypeScript the type for the return value.
Understanding Type Inference
Take the following type annotation:
What happens if you remove the type annotation?
You will find that TypeScript still types apples
as number
. This is an example of type inference.
Note: Type inference only works if variable declaration and initialization happen on the same line. So, if I do it on a separate line, TypeScript won't automatically infer the type for us:
When to Use Type Annotations vs. Type Inference
In general, we want to try to use type inference. That's because it means less code to write.
However, there are at least 3 situations when you need to use type annotations:
When a function returns the
any
type, and we need to clarify the valueWhen you declare a variable on one line and delay initialization for another line
When you want a variable to have a type that can't be inferred
Functions that returns the any
type
any
typeThe any
type is a type that tells TypeScript that we have no idea what type the variable is.
Some functions that depend on the input to determine the return type will return the any
type because it can't reasonably predict the return type.
For example, JSON.parse
could return any number of types depending on the JSON string you input. If you pass "'false'", you get back a boolean. If you pass '5'
, you get back a number.
However, allowing JSON.parse
to return the any
type wastes the potential of TypeScript. If you don't type your variables, you can't get helpful error messages if you do something wrong.
To solve this, we explicitly include a type annotation:
Delayed initialization
When you delay initialization, type inference doesn't work, and your variable is assigned the any
type.
Similar to the function case above, this is bad practice in TypeScript.
To solve this problem, we just apply type annotation.
When inference doesn't work
Type inference breaks down when the variable's type can be more than one type.
A real-world case of this might be you're storing a user's favouriteMedia
, and that variable could receive either a Book
instance, Movie
instance, or Song
instance.
To solve this, you can use the |
operator, which is sort of like an or operator for your types.
Since type inference doesn't support multiple types, you must type annotate to use the |
operator.
Last updated