Use unknown instead of any, it's safer

The `any` type turns off type checks, but the unknown type doesn't

With any, you turn off type check from TypeScript, which can be harmful. With unknown, your variables can still be of any type, but they are a safer way to build applications because you still get type checks.

any is a generic type in TypeScript which can be “anything”. It is often used to escape the type system instead of having to provide the exact types for different things:

let variable: any

variable.push() // TS says nothing
Object.values(variable) // TS says nothing
variable.startsWith() // TS says nothing

any is a placeholder for array so .push() could exist.

any is a placeholder for object so it can be passed as an argument to Object.values

any is a placeholder for string so .startsWith could exist.

The problem with this is that, it is not safe. TypeScript is supposed to help you identify type errors, but using any would turn off that support. If a variable is not an array, TypeScript should tell you .push() does not exist:

let variable: string = "hello"

variable./**/push/**/(5, 6)
Property 'push' does not exist on type 'string'

But TypeScript won’t say anything if you used any:

let variable: any = "hello"

variable.push(5, 6)

Sometimes you do not want to provide a type, or maybe a variable can be different types, so you just use any. However, there’s something even better can use: unknown.

unknown is like the safer version of any.

So what difference does unknown make?

With unknown, you are saying “this can be any type but I don’t know what that type is yet”. The beauty of this is that, before you use that variable for certain operations, you have to first “check” if that operation is possible.

Let’s look at the string example from earlier:

let variable: any = [1, 2]

variable.startsWith() // TS says nothing

// but this will throw an error during runtime
// because startsWith does not exist on a string

Here, variable is of any. But it actually holds an array, and arrays do not have a startsWith method. But TypeScript does not say anything. But let’s try unknown:

let variable: unknown = [1, 2]

/**/variable/**/.startsWith()
'variable' is of type 'unknown'

What you see here is TypeScript complaining. TypeScript is like “well, you just told me that you do ‘not know’ the type for this variable, so I cannot guarantee you that this variable has the startsWith method”.

So what if you wanted to use the startsWith method? Then you have to “tell” TypeScript that this is a string. How? Type Guards: o

let variable: unknown = [1, 2]

if (typeof variable === "string") {
  variable.startsWith() // TS says "we good"
}

By checking if variable is a string, then you give TypeScript the guarantee that you are working with a string, and so it approves the startsWith method.

This is why I say that unknown is a safer type than any. With any, you do not have to provide such checks. You could choose to do it, but you aren’t required to do to get TypeScript to stop yelling at you. But with unknown, you have to, to get a pass.

Type guards can exist in different ways. For example, you can use Array.isArray() to check if a value is of an array type:

let variable: unknown = [1, 2]

if (typeof variable === "string") {
  variable.startsWith() // TS says "we good"
}

if (Array.isArray(variable)) {
  variable.push(3, 4) // TS says "we good"
}

See how safe our applications are with type support?


So when you’re not sure what type to give a variable, instead of using any, go for unknown. While both types can mean “any type”, unknown ensures that you do type checks before proceeding to carrying out certain operations.