blog post

TypeScript: The Danger of Using the Any Keyword

A Big Thanks To The Sponsors of This Blog Post

Unlock limitless design potential with TailwindCSS components, transforming your UI development process into a breeze. Dive into a world of customizable, modern, and responsive components that elevate your user interface to new heights!

Learn more

Explore top-notch designs with Tailwind UI templates. Dive into a collection of user-friendly, responsive templates that make your projects shine!

Learn more

TypeScript has become a mainstream for web development for developers seeking to improve their JavaScript code with strong typing. TypeScript brings a level of type safety during compilation, increases code reliability and maintainability. These all is what JavaScript often lacks. TypeScript has different instruments and built-in types, most of them provide type safety and some of them provide flexibility. In this post, we'll take a look on one interesting keyword in TypeScript: any, we'll explore the danger of using any and learn how to use TypeScript's type system more effectively.

What is any and how it works?

The any keyword in TypeScript tells the compiler to trust you about the type of a variable, and it won't try to check its type during compilation. A variable of type any is like a JavaScript variable, freely mutable and usable in any context.

Let's have a look on example to see how any behaves in the code:

typescript
let data: any = "Hello, world!"; data = 42; // This code compiles without errors. data = true; // This code compiles as well.

The pitfalls of using any

1. No type safety

The primary drawback of using any is the loss of type safety, which is a primary advantage of TypeScript when comparing to JavaScript. Type safety helps to catch errors at compile time, but any bypasses these checks and errors may happen in the runtime like in this example:

typescript
let data: any = "Hello, world!"; data = 42; // This code compiles without errors. // Runtime error! Numbers don't have a toLowerCase method. console.log(data.toLowerCase());

Using type any for data variable in this example tells compiler to skip type checking for the variable usage. As a result an error is thrown in the runtime because data variable is not of type string and doesn't contain toLowerCase method.

2. Code readability and maintenance issues

Using any too liberally makes it harder to understand what type of data a function expects or returns, leading to potential bugs and future maintenance challenges. The main reason why many developers switched from JavaScript to TypeScript in the web development - is to have a compile time type safety. any keyword destroys this advantage.

3. Missed opportunities for intellisense

One of another advantage that TypeScript provides is a great intellisense. As all objects are statically typed - IDE can help to write the code. It is a known fact that TypeScript developers are more performant because of type safety and intellisense. With JavaScript you can only trust yourself, docs or guess what properties does the object have. While in the TypeScript, IDE can tell you object's type, all its properties, these all significantly increases coding performance.

I remember my college spending few hours debugging and fixing the bug in the Javascript's code, the problem was with one of types. In TypeScript he could have fixed the bug in a few minutes.

Alternatives to any keyword

While there are cases when any could be used - try to avoid it at all costs. One of possible uses cases for any is integration with javascript: you can use any if you can't create concrete types when integrating with existing javascript code.

Now let's have a look on alternatives.

1. Use specific types

Whenever possible, prefer specific types over any:

typescript
function sayHello(name: string): string { return `Hello, ${name}`; } let age: number = 25; sayHello("Anton");

2. Use discriminated unions

When a data shape can vary - discriminated unions can be used. Discriminated unions allow to combine multiple types into a single type where each option can be distinguished from the others:

typescript
type Square = { kind: 'square'; size: number; }; type Circle = { kind: 'circle'; radius: number; }; type Shape = Square | Circle; function countArea(shape: Shape) { switch (shape.kind) { case 'square': return shape.size * shape.size; case 'circle': return Math.PI * shape.radius * shape.radius; } }

This approach allows countArea function to accept different shapes while preserving type safety. It's a much safer option than using any.

3. Use unknown with type checks

When you're unsure of a type and you can't use other alternatives - you can use unknown. It's safer than any because it forces you to perform type checking before accessing the variable:

typescript
function sayHello(input: unknown) { if (typeof input === 'string') { console.log(input.toUpperCase()); // It's now safe to use string methods } } sayHello("Hello World");

Here, the process function checks if input is a string before calling string methods.

Summary

In TypeScript any is a tool that provide flexibility, especially when dealing with dynamic data or integrating with JavaScript. However, this flexibility often comes at the cost of type safety, which is TypeScript's primary strength. By utilizing any, you run the risk of introducing runtime errors and decreasing the code readability and maintainability.

While there are certain scenarios, you should avoid any at all costs, use it only as the last available option. Instead use concrete types, discriminated unions to unlock the full power of TypeScript's static type system to your advantage.

Hope you find this blog post useful. Happy coding!

Improve Your .NET and Architecture Skills

Join my community of 2000+ developers and architects.

Each week you will get 1 practical tip with best practises and architecture advice.