Typescript - Any vs Unknown
The Problem
any
is the most-capable type in Typescript. A lot of us may be guilty of using it just to “get stuff working first”.
const car: any = 'hyundai'
However, it weakens the type safety of your code and take away the benefits of type-checking in the language.
const car: any = 'hyundai'
/**
* Since car is of type any, all of these potentially
* erroneous calls will bypass compilation checks.
*/
car.honk()car.modelnew car()car()car `what a world`repair(car)
function repair(car: { status: string}) {
car.status = 'goodie good'
}
The Solution
As part of the Typescript 3.0 release, a new unknown
type was added to the blessed language.
Much like
any
, any value is assignable tounknown
; however, unlikeany
, you cannot access any properties on values with the typeunknown
, nor can you call/construct them. Furthermore, values of typeunknown
can only be assigned tounknown
orany
.
Going back to the above example, using unknown
instead of any
will give us compilation errors.
const car: unknown = 'hyundai'
/**
* All of these potentially erroneous calls will throw
* compilation errors.
*/
car.honk()
car.model
new car()
car()
car `what a world`
repair(car)
function repair(car: { status: string}) {
car.status = 'goodie good'
}
With type unknown
, we are forced to uphold type safety, and will be updating our code to enforce type checks.
Implement Type Checks
To get a workaround for our simple example, let’s start with declaring a type Car
.
type Car {
status: string
model: string
repair(): void
}
We can then implement a type guard.
function isTypeCar (obj: any): obj is Car {
return !!obj &&
typeof obj === 'object' &&
'model' in obj &&
'status' in obj &&
'honk' in obj &&
typeof obj.honk === 'function'
With the type guard, we can now use car
as we would like, and be rest-assured that type checks are enforced.
if (isTypeCar(car)) {
car.honk()
console.log(car.model)
repair(car)
}
Trying to use an invalid property or function would throw a compilation error.
if (isTypeCar(car)) {
car.honk()
console.log(car.model)
repair(car)
car() // throws compilation error}
That’s all. Happy programming!