Everyday TypeScript: Any
Welcome to the Any lesson!
This lesson is shown as static text below. However, it's designed to be used interactively. Click the button below to start!
TypeScript has a special type called
any. It means what it sounds like: a variable with this type can hold any value at all.>
const n: any = 5;n;Result:
5
>
const s: any = 'five';s;Result:
'five'
A value with the
anytype can be assigned to any variable, regardless of the variable's type.>
const n: any = 5;const n2: number = n;n2;Result:
5
You might ask yourself why we haven't told you this earlier. It makes everything so easy!
Yes, but it also prevents the type system from ensuring that variables have the types that we think they have. All bets are off when you use
any. For example, we can put a number in anany, then assign it to a variable of typestring. Doing that is wrong, but it won't cause a type error.>
const n: any = 5;const s: string = n;s;Result:
5
With
any, anything can be assigned to anything. We can do things that are complete nonsense, like assign a user object to a variable that's supposed to be an array of numbers.(The next example doesn't cause an error; the user will be in the
numbersvariable!)>
const user: any = {name: 'Amir'};const numbers: number[] = user;numbers;Result:
{name: 'Amir'}We can think of
anyas temporarily dropping us back into regular JavaScript, where everything is dynamically typed. For that reason, we recommend trying hard to avoidany. (Not because dynamic typing is "bad", but because the whole point of learning and using TypeScript is to get static guarantees!)Although
anyis undesirable, it still shows up in real-world code. Third-party libraries are one common example.TypeScript code often uses libraries that are written in JavaScript, not TypeScript. In many cases, the library's authors have added high-quality types to the original JavaScript, with little or no use of
any. In other cases, there may be a lot ofanys in the types. In extreme cases, every function in the library might useanyfor its parameter and return types, so we hardly get any type guarantees at all.Types with some
anys are usually better than having no type definitions at all. If a library truly has no TypeScript type definitions, then we have to write those types ourselves before using the library. (This was common in the past, but is unusual now. Most libraries have TypeScript types, and popular libraries tend to have quite good TypeScript types!) If the library's author has added types withany, that may cost us some safety, but at least we don't have to write types for the library ourselves!When we do use
any, how can we limit the danger? One way is to use conditional narrowing to bring the value back into the world of static types. For example, suppose that we use a JavaScript library to query a number from a database. The library's TypeScript type definitions aren't very good, so the number comes back with the typeany.We can use a type guard to narrow the type back to
number, throwing a runtime error if it's any other type. From that point forward, we can rely on the type system again. It won't let us assign thenumberto astringvariable, for example.(In these examples, you can type
errorif the code results in a runtime error viathrow. You can typetype errorif it will result in a compile-time type error.)>
function getNumberFromDatabase(): any {return 5;}- Note: this code example reuses elements (variables, etc.) defined in earlier examples.
>
function safeNumber(n: any): number {if (typeof n === 'number') {return n;} else {throw new Error('Got a non-number: ' + n);}} - Note: this code example reuses elements (variables, etc.) defined in earlier examples.
>
const n: any = 'five';const n2: number = safeNumber(n);Result:
Error: Got a non-number: five
- Note: this code example reuses elements (variables, etc.) defined in earlier examples.
>
const n: any = getNumberFromDatabase();const n2: number = safeNumber(n);n2;Result:
5
- Note: this code example reuses elements (variables, etc.) defined in earlier examples.
>
const n: any = getNumberFromDatabase();const n2: number = safeNumber(n);const s: string = n2;n2;Result:
type error: Type 'number' is not assignable to type 'string'.
Here's a code problem:
Use
anyto make the code below compile, even though it's wrong. (When building systems with TypeScript, remember to useanyonly as a last resort because you don't want this kind of bug in your code!)const n: any = 5;const s: string = n;s;- Goal:
5
- Yours:
5
The
anytype is another example of type unsoundness in TypeScript, an idea that we saw in an earlier lesson. In the case ofany, unsoundness is intentional. Creating a variable of typeanyeffectively tells TypeScript not to check the type at all, so all bets are off!