Stop using ANY in TypeScript right now. 🟦🧙‍♂️

alessandrofoglia07

Alessandro Foglia

Posted on October 26, 2023

Stop using ANY in TypeScript right now. 🟦🧙‍♂️

Hello coders! 🧙‍♂️

How many times in your career have you used the any type in TypeScript? Well, most people use this special type everyday, however what if I told you you should completely stop using it?

That's right. As a TypeScript developer, you should stop using any. Let's dive deeper into this and I'm sure I'll convince you at the end and you'll become a real TypeScript lover. 💙

When you don't know what type you should use in TypeScript. Any.

any type in TypeScript

The any type makes it into the category of "primitive types" in TypeScript. These are number, string, boolean, BigInt (from ES2020), symbol (not very common), undefined, null, void, never, unknown and lastly any.

However any is a special type, since it can be used when you don't want a particular value to cause typechecking errors.

TypeScript Documentation says:

When a value is of type any, you can access any properties of it (which will in turn be of type any), call it like a function, assign it to (or from) a value of any type, or pretty much anything else that’s syntactically legal.

And that's the reason why, unless you have some real issue, like libraries with no typing or old JavaScript code, you should never use any.

The unsafety of any

Since any type prevents any type-check, you can do literally whatever you want to do with it. E.g.:

let bar: any = { foo = 1 };
bar.foo; // Ok
bar.hello; // Ok ?
bar(); // Ok ??
bar.trim(); // ok???
new bar(); // ok...
bar[0][1][4]; // what the hell??
Enter fullscreen mode Exit fullscreen mode

This will not throw any compiler error and, unless really specific cases, it's absolutely wrong, since it totally destroys TypeScript purpose, type checking.

TypeScript as a knight with an armor. Arrow hits the knight perfectly on the only open way.

The type-safe any: unknown

Fortunately, for 100% code type-safety, there's an alternative for any, the unknown type.

The unknown type works the same as any, but with compiler errors if you don't specify the exact type you expect. For clarity, here's an example:

let safeBar: unknown = "Hello world";
safeBar.hello; // Error thrown
safeBar(); // Error thrown
// etc...
Enter fullscreen mode Exit fullscreen mode

This could be useful in case you literally don't know what type a variable is. Check this other example:

function parseApiResponse(response: string): unknown {
    try {
        return JSON.parse(response);
    } catch (error) {
        return null;
    }
}

const apiResponse = '{ "name": "John", "age": 30 }';
const parsedData = parseApiResponse(apiResponse);

if (typeof parsedData === 'object') {
    // Now, you can safely access properties without TypeScript errors
    const name = (parsedData as { name: string }).name;
    const age = (parsedData as { age: number }).age;

    console.log(`Name: ${name}, Age: ${age}`);
} else {
    console.log('Failed to parse API response');
}
Enter fullscreen mode Exit fullscreen mode

In this example, the "parseApiResponse" function returns data of type "unknown" because the actual structure of the data is not known at compile time. You can use type assertions (e.g., (parsedData as { name: string }).name) to access properties safely when you've checked the type. This way, you maintain type safety even when dealing with data of an unknown structure.

How to prevent any in your code

You can start preventing any in your code by modifying your tsconfig.json file. Set the noImplicitAny property to true, to check if no type annotations are present for a variable. Normally, in that case, TypeScript will fall back to a type of any for a variable when it cannot infer the type.

{
  "compilerOptions": {
    /* ... */
    "noImplicitAny": true,
    /* ... */
  }
}
Enter fullscreen mode Exit fullscreen mode

Check this example:
With noImplicitAny: false:

function fn(s) {
  // No error?
  console.log(s.subtr(3));
}
fn(42);
Enter fullscreen mode Exit fullscreen mode

With noImplicitAny: true:

function fn(s) {
// Error: Parameter 's' implicitly has an 'any' type.
  console.log(s.subtr(3));
}
Enter fullscreen mode Exit fullscreen mode

If you use EsLint as your main linter, you may also install @typescript-eslint plugin to get the noExplicitAny rule. Example:

function fn(s: any): any {
// Error: Unexpected any. Specify a different type. - eslint@typescript-eslint/no-explicit-any
  console.log(s);
  return s;
}
Enter fullscreen mode Exit fullscreen mode

Who am I?

I am an Italian high-school student who is interested in web-dev 🧙‍♂️. If you'd like to support me, you can follow me here and on my GitHub, I would really appreciate it 💜

💖 💪 🙅 🚩
alessandrofoglia07
Alessandro Foglia

Posted on October 26, 2023

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related