TypeScript Data Types

TypeScript's primary strength lies in its type system. By defining data types, you allow the compiler to act as a safety net, catching errors during development rather than at runtime. This leads to more predictable code and a much better "IntelliSense" experience in your editor.

 

Basic Data Types

Number

Unlike some languages that distinguish between integers, floats, and doubles, TypeScript treats all numeric values as number. This includes whole numbers, decimals, and even hexadecimal or binary notation.

let age: number = 25; // Integer
let pi: number = 3.14; // Floating-point
let hex: number = 0xf00d; // Hexadecimal
let binary: number = 0b1010; // Binary

console.log(age, pi); // Output: 25 3.14
Best Practice: While TypeScript can often infer types (e.g., let x = 10), explicitly typing your variables is helpful in complex logic or function signatures to ensure the intended type is always maintained.

String

The string type handles textual data. You can use single quotes, double quotes, or backticks for template literals, which allow you to embed variables directly into the text.

let name: string = "John Doe";
let greeting: string = `Hello, ${name}, welcome to the team!`;

console.log(greeting); // Output: Hello, John Doe, welcome to the team!
Developer Tip: Use template literals (backticks) whenever you need to concatenate strings and variables. It's much cleaner and less error-prone than using the + operator.

Boolean

The boolean type is the simplest of all, representing a logical true or false. It is most commonly used in conditional statements and flags.

let isActive: boolean = true;
let hasPermission: boolean = false;

if (isActive) {
  console.log("The user is active.");
}

 

Special Data Types

Any

The any type is an "escape hatch" that tells TypeScript to opt out of type-checking for that variable. While powerful, it effectively turns off the benefits of using TypeScript.

let anything: any = "Hello";
anything = 42; // This is allowed
anything = true; // This is also allowed
Watch Out: Overusing any makes your code behave like plain JavaScript. Use it sparingly, only when dealing with dynamic content where the type truly cannot be known beforehand.

Unknown

The unknown type is the type-safe sibling of any. You can assign anything to unknown, but you cannot perform operations on it until you explicitly check its type (type narrowing).

let unknownValue: unknown = "Test";

// unknownValue.toUpperCase(); // Error: 'unknownValue' is of type 'unknown'.

if (typeof unknownValue === "string") {
  console.log(unknownValue.toUpperCase()); // Now it's safe! Output: TEST
}
Common Mistake: Beginners often use any when they should be using unknown. If you don't know the type yet (like from a 3rd party API), use unknown to force yourself to validate the data later.

Null and Undefined

In TypeScript, null represents an intentional absence of value, while undefined means a variable has been declared but not yet assigned a value.

let empty: null = null;
let notAssigned: undefined = undefined;

console.log(empty, notAssigned); // Output: null undefined

 

Advanced Data Types

Array

Arrays allow you to store collections of values. You can define an array type using the type[] syntax or the generic Array<type> syntax.

let numbers: number[] = [1, 2, 3, 4];
let fruits: Array<string> = ["Apple", "Banana", "Cherry"];

numbers.push(5); // Valid
// numbers.push("six"); // Error: Argument of type 'string' is not assignable to parameter of type 'number'.

Tuple

A tuple is a specialized array with a fixed number of elements where each element has a predefined type. These are excellent for representing data structures like coordinates or key-value pairs.

let person: [string, number] = ["Alice", 30];
let coordinates: [number, number] = [40.7128, -74.0060];

console.log(person[0]); // Alice
Watch Out: While you can use .push() on a tuple, TypeScript won't catch the error if you add extra elements. Be careful not to treat tuples as dynamic arrays.

Enum

Enums (Enumerations) allow you to define a set of named constants. This makes your code more readable and self-documenting by replacing "magic numbers" or "magic strings."

enum OrderStatus {
  Pending,   // 0
  Shipped,   // 1
  Delivered, // 2
  Cancelled  // 3
}

let status: OrderStatus = OrderStatus.Shipped;
console.log(status); // Output: 1
Best Practice: Consider using String Enums (e.g., Pending = "PENDING") for better debugging, as the string value is more descriptive than a number when looking at logs.

Object

The object type represents any non-primitive type. However, it is more common to define the specific shape of an object using curly braces to ensure all required properties are present.

let user: { name: string; age: number; isAdmin?: boolean } = { 
  name: "Bob", 
  age: 28 
};

// Note: isAdmin is optional because of the '?'
console.log(user.name);

Union

A union type allows a variable to be one of several types. This is incredibly useful for variables that might transition from a numeric ID to a string UUID.

let id: string | number;

id = 123; // Valid
id = "ABC-789"; // Valid

function printId(id: string | number) {
  console.log(`Your ID is: ${id}`);
}

Void

void is commonly used as the return type for functions that perform an action but do not return a value (like logging to a console or saving to a database).

function logMessage(message: string): void {
  console.log(message);
  // No return statement here
}

Never

The never type represents a value that will *never* occur. You'll see this in functions that always throw an error or in infinite loops that never reach a completion point.

function throwError(message: string): never {
  throw new Error(message);
}

function infiniteLoop(): never {
  while (true) {}
}

 

Summary

TypeScript provides a robust toolkit of data types that cater to both simple and complex scenarios. By mastering basic types like string and number, and moving into advanced types like unions, tuples, and enums, you can write code that is self-documenting and significantly more resistant to common bugs. Always aim for the most specific type possible to get the most value out of the TypeScript compiler.