Skip to main content

Understanding the Difference Between Generics and the Unknown Type in TypeScript

· 3 min read

TypeScript's type system brings a level of safety and predictability to JavaScript that allows developers to write more maintainable and error-resistant code. Among its features are generics and the unknown type, both empowering developers to handle various scenarios with precision.

However, they serve distinct purposes. In this article, we'll explore how generics differ from the unknown type and when to use each one.

What are Generics?

Generics are one of the most powerful features of TypeScript, designed to enable components to handle a variety of types rather than a single one. They allow you to capture the type a user provides (for example, when calling a function), and then use that type to enforce consistency throughout the component's interactions.

Consider this generic function:

function identity<T>(arg: T): T {
return arg;
}

You can explicitly specify the type when calling this function:

let output = identity<string>("myString");

Or, let TypeScript infer the type:

let output = identity("myString"); // inferred as string

Here, T is a placeholder for any type, not an actual type like unknown. It ensures that whatever type you put in is the type you get out, maintaining a consistent contract.

The unknown Type

The unknown type is TypeScript's safer alternative to the any type. While any allows for complete freedom and JavaScript-like flexibility, thereby circumventing TypeScript's checking mechanisms, unknown is much stricter. You can't perform any operations on values of type unknown without first narrowing them down to a more specific type.

Here's an example:

let value: unknown;

value = 5; // OK
value = "hello"; // OK

let stringValue: string = value; // Error: 'unknown' is not assignable to 'string'.

To use the unknown value safely, you'd need to verify its type:

if (typeof value === "string") {
stringValue = value; // Now it's safe, within this block 'value' is a string
}

Key Differences

  • Purpose: Generics are meant to provide flexibility with type safety, enabling one to write a single piece of code that can operate on different types. On the other hand, unknown is used when the type is uncertain, and it restricts operations on a value until its type is verified.

  • Type Safety: Generics keep the relationship between the input and output types intact, preserving type information throughout the component. The unknown type is a mechanism that forces you to ensure the type of a value before any manipulation.

  • Flexibility vs. Restriction: Generics add flexibility by letting you work with any type in a uniform manner. Conversely, unknown acts as a restrictive placeholder that demands type-checking before any operation can be performed.

  • Use Cases: Employ generics when you aim to create components that can interact with various types while maintaining type relationships. Use unknown when dealing with values from dynamic sources and you require robust type-checking for safety.

Conclusion

Generics and the unknown type cater to different needs within TypeScript's ecosystem. Generics provide a way to write flexible, yet type-safe code, making it ideal for creating reusable components. The unknown type is geared towards maintaining strict type safety when dealing with variable inputs, ensuring that developers don't make unfounded assumptions about the data they work with.

By understanding and utilizing generics and the unknown type appropriately, TypeScript developers can take full advantage of the language's capabilities to write robust, error-resistant applications.

What Can You Do Next 🙏😊

If you liked the article, consider subscribing to Cloudaffle, my YouTube Channel, where I keep posting in-depth tutorials and all edutainment stuff for ssoftware developers.

YouTube @cloudaffle