Why any is bad
They any
type in TypeScript is usually considered unsafe 99.99% of the time. This is why any
is so dangerous:
const str: any = 'I am a string'
const num: number = str
num // 'I am a string'
Even though we're telling TS that num
must be of type number
, because the type of str
is any
it can easily be assigned to num
even if the value is not a number
.
Like I said, 99.99% of the time, any
is bad. But there is one case in TypeScript where it's completely type safe to use any
!
Generic constraints
When we are working with generics in TS we can constrain the generic using the extends
keyword.
For example I might have a PetOwner
type that has a list of pets, but I want it to be generic so that I can make the array contain only cats, or only dogs.
type PetOwner<T extends Array> = {
pets: T
}
This type will currently cause a type error because the Array
type requires a type argument. So lets give it one:
type PetOwner<T extends Array<any> = {
pets: T
}
Now at first you may think that this is dangerous. We're using any
! But lets look at what actually happens when we use this type:
const dogLover: PetOwner<Dog[]>
What is the type of dogLover
here? If you gessed {pets: Array<Dog>}
you're correct!
This is because when any
is used in a generic constraint, TypeScript discards it and replaces it with whatever the type argument was, assuming that it matches the constraint. Dog[]
matches the constraint of Array<any>
so T
gets the type Dog[]
.
⚠
any
is still dangerous if you use it as a type argument. If I instead usedPetOwner<any[]>
it would have all the same pitfalls as usingany
in any other context outside of a generic constraint.
A note on unknown
unknown
behaves exactly the same way as any
in this context, so it may be preferable to use unknown
but it’s totally up to preference.
For myself, I think any
reads better. It describes the intent of the type code more clearly. T must be an array, but it can be an array of anything. Using unknown
doesn't convey that message as well in my opinion.
Top comments (0)