avatarBytefer

Summarize

Type Challenges: Implement the IsAny<T> Utility Type

99% of TypeScript Developers Have Used the Any Type. But Only 20% of Developers Know How To Detect Any Type.

Welcome to the Mastering TypeScript series, there are dozens of articles in this series. To help readers better consolidate their knowledge of TypeScript, I have selected a few dozen challenges from the type-challenges repository on Github to complete the type challenge with you.

Challenge

Sometimes it’s useful to detect if you have a value with any type. This is especially helpful while working with third-party TypeScript modules, which can export any values in the module API. It's also good to know about any when you're suppressing implicitAny checks.

So, let’s write a utility type IsAny<T>, which takes input type T. If T is any, return true, otherwise, return false.

For example:

type A = IsAny<any> // expected to be true
type B = IsAny<undefined> // expected to be false
type C = IsAny<unknown> // expected to be false
type D = IsAny<never> // expected to be false
type E = IsAny<string> // expected to be false

Solution

Our type challenge is to implement the IsAny<T> generic, before we analyze how to implement this generic type, let’s briefly introduce the any type.

Any Type

In TypeScript, any type is called the top type. The so-called top type can be understood as a generic parent type, that is, a type that can contain all values.

In fact, any type is essentially an escape hatch for the type system, and TypeScript allows us to perform any operation on the value of any type without performing any kind of prior checking.

What’s the problem with this? Let’s take an example:

For the above TypeScript code, no errors will be prompted at compile time, but runtime errors will be thrown at runtime. As developers, any type gives us a lot of freedom, but it also brings some pitfalls. In order to solve the security risks of any type, the TypeScript team introduced the unknown type in 3.0, which you can understand as a type-safe any type.

I won’t go into the difference between any type and unknown type, but you can read the following article if you are interested.

Finally, let’s look at the complete code:

type IsAny<T> = 0 extends T & 1 ? true : false
type A = IsAny<any> // true
type B = IsAny<undefined> // false
type C = IsAny<unknown> // false
type D = IsAny<never> // false
type E = IsAny<string> // false

In TypeScript, the & operator is provided for us to implement the intersection operation on multiple types, and the resulting new type is called the intersection type.

Let’s briefly introduce the & operator, which satisfies the following rules:

  • Identity: A & A is equivalent to A.
  • Commutativity: A & B is equivalent to B & A (except for call and construct signatures as noted below).
  • Associativity: (A & B) & C is equivalent to A & (B & C).
  • Supertype collapsing: A & B is equivalent to A if B is a supertype of A.

In the above code, any type and never type are special. Except for the never type, other type intersecting with any type will result in any type.

After understanding the characteristics of the any type, let’s take a look at the output of T & 1 when the T type parameter is of a different type:

type A1 = any & 1 // any
type B1 = undefined & 1 // never
type C1 = unknown & 1 // 1
type D1 = never & 1 // never
type E1 = string & 1 // never

After mastering the above content, the rest is the related content of TypeScript conditional types, which will not be introduced here. I recommend you to read this article:

If there is anything unclear, please leave me a message. You also can follow me on Medium or Twitter to read more about TypeScript and JavaScript!

Resources

Typescript
JavaScript
Front End Development
Web Development
Programming
Recommended from ReadMedium