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[].
⚠
anyis still dangerous if you use it as a type argument. If I instead usedPetOwner<any[]>it would have all the same pitfalls as usinganyin 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)