TypeScript / Type Annotation vs Type Assertion
By default, the TypeScript compiler tries its best to analyze the code and infer the type of your variables.
let a = 10; // typeof a == number
let b = "hello"; // typeof b == string
Type Assertion is when you tell the compiler that you know a variable has a specific type, so it doesn’t have to make a guess:
let a: any = 10;
let b = a as number;
This might be helpful in some cases when TypeScript does not have enough information about the type of some values, for example:
const parsedData = JSON.parse(data) as SomeType;
// or
const ref = useRef<HTMLInputElement>(null);
Type Annotation is when you tell the compiler that a variable is expected to have a specific type, and if it’s not, it should be a bug:
let a: number = "hello"; // Error!
type Foo {
one: string;
two: number;
};
let b: Foo = { one: "hello", two: 10 }; // OK
Using type assertion might be helpful in some cases, but it will weaken the type checking feature of TypeScript. Let’s take a look at the following example:
let a = { one: "hello" } as Foo; // No error
let b: Foo = { one: "hello" }; // Error
As mentioned earlier, TypeScript will try to infer the type for both a
and b
, and in this case, both have the shape of { one: string }
.
Since we convinced TypeScript that the type of a
is Foo
, even if this seems to be a mismatch, TypeScript will trust you and ignore the type error. It’s not the case for b
, TypeScript knows that we are expecting a type { one: string, two: number }
instead of a { one: string }
.
Note that, if the shape of a
is clearly mismatched with Foo
, TypeScript will be able to stop you:
let a = { one: "hello", two: "world" } as Foo; // Error
So, it’s a best practice to prefer type annotation over type assertion in most cases.