Secrets of ‘unknown’ Types in TypeScript

Why ‘unknown’ Is preferred over ‘any’ in TypeScript?

Zachary Lee
Better Programming

--

This post will introduce the unknown type in TypeScript, which was introduced in TypeScript 3.0 and is the type-safe counterpart of any.

Why do I say this? Next, I will show the characteristics of unknown type and its advantages compared with any, let's get started!

Assignability

All types are assignable to unknown, but in turn, unknown can only be assigned to itself and any.

Intersection Types

In intersection types, all types will absorb unknown.

This is not difficult to understand, because the intersection type represents the intersection of the two, and we already know in the previous section that all types are assignable to unknown, so any intersection with unknown will be itself.

Union Types

In union types, unknown absorbs all types except any.

The union type represents the combination of the two. If the two can be combined, then the one with the more relaxed range will be returned, so it is unknown except for any.

Keyword `keyof`

keyof unknown returns the type never, representing the type of the value that will never occur. Whereas keyof any returns the type of any value that can be used as an object index. Why do you say that?

This is because there is a keyofStringsOnly in the TypeScript compilation options, the default is false, then keyof any will return string | number | symbol type, When true, keyof any will return type string.

It’s worth noting that the built-in advanced type Record in TypeScript uses this to qualify types that can be used as object indexes. Its source code is as follows:

type Record<K extends keyof any, T> = {
[P in K]: T;
};

For more information on built-in utility types in TypeScript, please check out my previous article:

For the secrets of never types in TypeScript, check out my other article:

Initialized

unknown variables declared without const are always considered initialized.

Restrictions before narrowing types

Except for the equality operators, you cannot use any other operators, such as +-*/ , property access, function calls, etc., without narrowing the type of unknown.

Narrow type

From the previous section, we know that if we want to manipulate the value of the unknown type, we must first narrow the type, so that the TypeScript compiler knows what we are doing, and your code is guaranteed to be safe.

Narrowing types can use typeof, instanceof, user-defined type predicates, type assertions, etc.

Note that TypeScript doesn’t help us perform any checks when using type assertions, which means you have to know what you’re doing and make sure you’re doing what you want.

Conclusion

The any type causes the TypeScript compiler to skip type checking for this variable, which can be understood as an escape hatch into the TypeScript type system, but in most cases, it's too lenient. On the other hand, values of type unknown must be narrowed down to a specific type before most operations are performed, which often means safer and more robust.

Thanks for reading. I hope this was helpful. If you are interested, check out my other Medium articles.

--

--