ZetCode

TypeScript's any Type

Last modified November 12, 2025

The any type in TypeScript is a powerful but potentially dangerous tool. It disables type checking for a variable or expression, allowing you to assign any value and call any property or method without compile-time errors. While this can be useful when dealing with dynamic or untyped data, it sacrifices the type safety that TypeScript is designed to provide. This article explores the any type, corrects common misconceptions, and provides practical examples and best practices.

TypeScript enforces static typing to catch errors at compile time. However, the any type opts out of this system, treating values as if they could be of any type. any is often used as a fallback when integrating with JavaScript, handling third-party libraries, or working with data of unknown structure. While convenient, overuse can undermine TypeScript's benefits, making code harder to maintain and debug.

Basic Usage of Any

The any type allows a variable to hold any value without type restrictions. This example demonstrates its basic flexibility:

basic_any.ts
let value: any = 42;
value = "Hello";
value = true;
value = [1, 2, 3];
value = { foo: "bar" };

console.log(value); // Output: { foo: "bar" }

The variable value is declared with type any, allowing it to be assigned a number, a string, a boolean, an array, and finally an object. TypeScript does not enforce type consistency here.

This flexibility is useful when the type is unknown initially, such as with dynamic user input, but it bypasses type safety and can hide errors until runtime.

Any with Functions

Functions can use any for parameters or return types when types are unpredictable. This example processes an unknown input:

any_function.ts
function processInput(input: any): any {
    // You can do anything with input, but lose type safety
    return input;
}

console.log(processInput(5));      // Output: 5
console.log(processInput("test")); // Output: test
console.log(processInput([1, 2])); // Output: [1, 2]

The processInput function accepts an any-typed parameter and returns any. It can handle numbers, strings, arrays, or any other type without type errors.

Warning: If you call input.toUpperCase inside this function, it will compile even if input is a number or array, leading to runtime errors.

Any with Objects

Objects typed as any allow unrestricted property access. This example manipulates an untyped object:

any_object.ts
let data: any = { name: "Alice" };
data.age = 30;
data.active = true;
data.nonExistentMethod(); // Compiles, but will throw at runtime

console.log(data);

The data variable, typed as any, starts as an object with a name property. It then accepts new properties (age, active) and even allows calling non-existent methods without compile-time errors.

This is useful for dynamic data, like JSON from an API, but accessing data.foo or calling data.nonExistentMethod compiles despite potential runtime issues, reducing safety.

Any with Arrays

Arrays typed as any can hold mixed types. This example builds a heterogeneous array:

any_array.ts
let mixed: any[] = [1, "two"];
mixed.push(true);
mixed.push({ key: "value" });
mixed.push([1, 2, 3]);

console.log(mixed); // Output: [1, "two", true, { key: "value" }, [1,2,3]]

The mixed array, typed as any[], starts with a number and a string. It then accepts a boolean, an object, and another array via push, all without type errors.

This suits scenarios with unpredictable array contents, but operations like mixed[0].toUpperCase compile even if invalid, risking runtime errors.

Implicit Any

TypeScript infers any when types aren't specified, unless noImplicitAny is enabled. This example shows implicit any:

implicit_any.ts
// With `noImplicitAny: false` in tsconfig.json
function logValue(value) {
    // value is implicitly any
    console.log(value);
}

logValue(42);      // Output: 42
logValue("Hello"); // Output: Hello
logValue([1, 2]);  // Output: [1, 2]

Without a type annotation, value in logValue is implicitly any if noImplicitAny is off. It accepts any input and logs them without compile-time checks.

With noImplicitAny: true, TypeScript would error, requiring an explicit type. Implicit any mimics JavaScript's flexibility but weakens type safety.

Any with Type Assertions

Type assertions can refine any-typed values when their type is known. This example asserts a type from any:

any_assertion.ts
let rawData: any = "Hello World";
const str: string = rawData as string;

console.log(str.toUpperCase()); // Output: HELLO WORLD

The rawData variable is any, holding a string. The as string assertion tells TypeScript to treat it as a string, enabling toUpperCase.

Without assertion, rawData.toUpperCase compiles but isn't type-safe. Assertions bridge any to typed code, but require developer certainty.

Any in Third-Party Libraries

The any type is common when typing untyped library outputs. This example simulates an untyped API response:

any_library.ts
// Simulating an untyped library function
declare function fetchData(): any;

const response = fetchData();
response.name = "Test";
console.log(response.name); // Output: Test (assumed)

The fetchData function, declared as returning any, mimics an untyped library. The response variable accepts any modification, like adding a name property.

This is practical for untyped JavaScript libraries, but risks runtime errors if assumptions (e.g., response.name exists) fail.

Any with Dynamic Data

Dynamic data, like JSON, often uses any initially. This example parses JSON with any:

any_json.ts
const jsonString = '{"id": 1, "title": "Book"}';
const parsed: any = JSON.parse(jsonString);

console.log(parsed.title); // Output: Book
console.log(parsed.nonexistent); // Compiles, but undefined at runtime

The parsed variable, typed as any, holds the result of JSON.parse, which TypeScript can't type precisely without context. It allows accessing title directly, but also allows accessing properties that don't exist, which will be undefined at runtime.

This is useful for quick prototyping with dynamic data, but needs refinement for safety.

Any vs. Unknown

TypeScript also provides the unknown type, which is safer than any. Unlike any, you cannot access properties or call methods on an unknown value without first asserting or narrowing its type:

any_vs_unknown.ts
let a: any = 123;
a.foo(); // Compiles, but will throw at runtime

let u: unknown = 123;
// u.foo(); // Error: Object is of type 'unknown'.

if (typeof u === "object" && u !== null) {
    // Now safe to access properties
}

Prefer unknown when you want to force type checking before using a value.

Type Erasure and Risks

Using any erases all type information. TypeScript will not check property names, method calls, or assignments. This can lead to subtle bugs:

type_erasure.ts
let user: any = { name: "Bob" };
console.log(user.nmae); // Compiles, but typo! Outputs undefined

Typos and incorrect assumptions will not be caught at compile time.

Best Practices

Source

TypeScript Any Type Documentation

This tutorial covered TypeScript's any type with practical examples and warnings. Use it judiciously to balance flexibility and type safety in your code.

Author

My name is Jan Bodnar, and I am a passionate programmer with extensive programming experience. I have been writing programming articles since 2007. To date, I have authored over 1,400 articles and 8 e-books. I possess more than ten years of experience in teaching programming.

List all TypeScript tutorials.