DEV Community

Matheus Morett
Matheus Morett

Posted on

Why You Shouldn't Use `as` in TypeScript 🚫

Introduction

TypeScript, since its inception, has aimed to provide static typing for JavaScript, helping developers write safer and more reliable code. The as operator was introduced to allow type assertions, a powerful feature but one with great potential for misuse. In this article, we'll explore the creation and purpose of as, common mistakes associated with its use, and how alternatives like zod can offer a more robust solution.

The Creation of as in TypeScript

The as keyword in TypeScript is used to inform the compiler that a value should be treated as a specific type, regardless of its original inference. It's useful in situations where the developer is certain about the correct type of a variable, but the compiler cannot infer it.

For example:

const value: unknown = getValueFromSomewhere();
const valueAsString = value as string; // I know `value` is a string!
Enter fullscreen mode Exit fullscreen mode

In this case, as tells the compiler that value is a string, even though it was initially inferred as unknown.

Common Mistake: Using as with Fetch and JSON.parse

While as is useful, it can easily be misused, especially in scenarios where data comes from external sources, such as APIs.

With Fetch

When using fetch to get data from an API, it's tempting to use as to tell TypeScript what type of data to expect:

async function fetchData() {
    const response = await fetch('https://api.example.com/data');
    const data = await response.json() as MyDataType; // Beware!
    return data;
}
Enter fullscreen mode Exit fullscreen mode

Here, we're telling TypeScript: "Trust me, data is of type MyDataType." The problem is that fetch doesn't guarantee the format of the returned data. This can lead to runtime errors that TypeScript cannot predict or prevent.

With JSON.parse

The same issue arises when using JSON.parse():

const jsonString = '{"name": "John", "age": 30}';
const parsedData = JSON.parse(jsonString) as MyDataType; // Risky!
Enter fullscreen mode Exit fullscreen mode

Although jsonString seems to contain an object of type MyDataType, there are no guarantees. If the JSON structure changes or is incorrect, the code will fail silently, leading to hard-to-track bugs.

The Solution: Using zod for Safe Type Validation

To avoid these issues, it's better to validate external data before trusting it. zod is a TypeScript schema validation library that can be used for this purpose.

Example with fetch and zod

import { z } from 'zod';

const MyDataType = z.object({
    name: z.string(),
    age: z.number(),
});

async function fetchData() {
    const response = await fetch('https://api.example.com/data');
    const json = await response.json();

    const result = MyDataType.safeParse(json);
    if (!result.success) {
        throw new Error('Invalid data');
    }

    return result.data; // Now we are sure that `result.data` is of the correct type!
}
Enter fullscreen mode Exit fullscreen mode

Example with JSON.parse and zod

const jsonString = '{"name": "John", "age": 30}';
const json = JSON.parse(jsonString);

const result = MyDataType.safeParse(json);
if (!result.success) {
    console.error(result.error);
} else {
    console.log('Valid data:', result.data);
}
Enter fullscreen mode Exit fullscreen mode

When It’s Safe to Use as

Although we’ve discussed the dangers of misusing as, there is one specific scenario where I personally find it acceptable to use: Gradual Migration to TypeScript.

Gradual Migration to TypeScript

During the migration of a large JavaScript codebase to TypeScript, it might be necessary to use as temporarily to maintain compatibility while you gradually add more specific and safe types to your code.

function processData(data: any) {
    const typedData = data as MyDataType; // Temporary use
    // Processing logic here
}
Enter fullscreen mode Exit fullscreen mode

This is an acceptable use of as during the transition but should be replaced by more precise types or validations as soon as possible.

Conclusion

While as can be a handy tool, its misuse, especially when dealing with dynamic or external data, can lead to silent and hard-to-debug runtime errors. Instead, adopting validation tools like zod provides a more robust and secure approach, ensuring that data matches the expected types before trusting it in your TypeScript code. Personally, I would only use as in the context of gradual migration to TypeScript, where its temporary nature is understood, and plans are in place to phase it out.

Top comments (0)