any
and unknown
any
JSON.parse()
String()
unknown
In TypeScript, any
and unknown
are types that contain all values. In this chapter, we examine what they are and what they can be used for.
any
and unknown
are so-called top types in TypeScript. Quoting Wikipedia:
The top type […] is the universal type, sometimes called the universal supertype as all other types in any given type system are subtypes […]. In most cases it is the type which contains every possible [value] in the type system of interest.
That is, when viewing types as sets of values (for more information on what types are, see [content not included]), any
and unknown
are sets that contain all values. As an aside, TypeScript also has the bottom type never
, which is the empty set.
any
If a value has type any
, we can do everything with it:
function func(value: any) {
// Only allowed for numbers, but they are a subtype of `any`
5 * value;
// Normally the type signature of `value` must contain .propName
.propName;
value
// Normally only allowed for Arrays and types with index signatures
123];
value[ }
Every type is assignable to type any
:
: any;
let storageLocation
= null;
storageLocation = true;
storageLocation = {}; storageLocation
Type any
is assignable to every type:
function func(value: any) {
: null = value;
const a: boolean = value;
const b: object = value;
const c }
With any
we lose any protection that is normally given to us by TypeScript’s static type system. Therefore, it should only be used as a last resort, if we can’t use more specific types or unknown
.
JSON.parse()
The result of JSON.parse()
depends on dynamic input, which is why the return type is any
(I have omitted the parameter reviver
from the signature):
JSON.parse(text: string): any;
JSON.parse()
was added to TypeScript before the type unknown
existed. Otherwise, its return type would probably be unknown
.
String()
The function String()
, which converts arbitrary values to strings, has the following type signature:
interface StringConstructor {?: any): string; // call signature
(value// ···
}
unknown
The type unknown
is a type-safe version of the type any
. Whenever you are thinking of using any
, try using unknown
first.
Where any
allows us to do anything, unknown
is much more restrictive.
Before we can perform any operation on values of type unknown
, we must first narrow their types via:
function func(value: unknown) {
// @ts-expect-error: Object is of type 'unknown'.
.toFixed(2);
value
// Type assertion:
as number).toFixed(2); // OK
(value }
Equality:
function func(value: unknown) {
// @ts-expect-error: Object is of type 'unknown'.
* 5;
value
if (value === 123) { // equality
// %inferred-type: 123
;
value
* 5; // OK
value
} }
function func(value: unknown) {
// @ts-expect-error: Object is of type 'unknown'.
.length;
value
if (typeof value === 'string') { // type guard
// %inferred-type: string
;
value
.length; // OK
value
} }
function func(value: unknown) {
// @ts-expect-error: Object is of type 'unknown'.
.test('abc');
value
assertIsRegExp(value);
// %inferred-type: RegExp
;
value
.test('abc'); // OK
value
}
/** An assertion function */
function assertIsRegExp(arg: unknown): asserts arg is RegExp {
if (! (arg instanceof RegExp)) {
new TypeError('Not a RegExp: ' + arg);
throw
} }