# ✨ Mastering TypeScript Fundamentals: Annotations, Inference, any, Function Parameters & void Type

# Introduction

Whether you're a JavaScript developer dipping your toes into TypeScript or someone refining their TypeScript skills, understanding the **core typing system** is essential. In this article, we'll deeply explore:

1. **Type Annotations**
    
2. **Type Inference**
    
3. **The** `any` Type
    
4. **Function Parameters with Annotations**
    
5. **The** `void` Return Type
    

---

## 1️⃣ Type Annotations: Adding a Label to Your Data

**Definition:** Type annotations explicitly define the type of a variable, parameter, or return value. Think of it as adding a "name tag" to your data that tells TypeScript what kind of value to expect.

### 📌 Why Use Annotations?

* Catches errors **at compile time**
    
* Improves **editor autocompletion**
    
* Makes code **self-documenting**
    

### 🧪 Example 1: Basic Variable Annotations

```typescript
let name: string = "Alice";
let age: number = 28;
let isLoggedIn: boolean = true;
```

Here, you're telling TypeScript:

* `name` must always be a string
    
* `age` must be a number
    
* `isLoggedIn` must be a boolean
    

### ❌ Error Example:

```typescript
name = 42; // Error: Type 'number' is not assignable to type 'string'
```

### 🧪 Example 2: Array and Object Annotations

```typescript
let scores: number[] = [95, 82, 77];  // Array of numbers
let user: { id: number; username: string } = {
  id: 1,
  username: "coder123",
};
```

### 🧪 Example 3: Union Types

Allow multiple possible types:

```typescript
let status: string | number;
status = "loading"; // OK
status = 200;       // OK
status = true;      // ❌ Error
```

---

## 2️⃣ Type Inference: When TypeScript Reads Your Mind

**Definition:** TypeScript can automatically infer the type of a variable if it's initialized with a value.

### 🧪 Example 1: Inferred Types

```typescript
let language = "TypeScript"; // inferred as string
let version = 5.4;           // inferred as number
```

This works **only** when you initialize a variable right away.

### 🔍 How It Helps:

```typescript
language.toUpperCase(); // IntelliSense knows it's a string!
version.toFixed(1);     // Works because it's inferred as number
```

### 🧪 Example 2: No Initialization

```typescript
let result; // inferred as `any` (not good)
result = "Success";
result = 100; // No error — ⚠️ dangerous!
```

✅ Best Practice: Always initialize variables or explicitly annotate them to avoid unintended `any` usage.

---

## 3️⃣ The `any` Type: The Escape Hatch

**Definition:** The `any` type disables type checking — it tells TypeScript: “I know what I’m doing!”

```typescript
let mysteryData: any = "Text";
mysteryData = 42;
mysteryData = true;
```

It behaves like JavaScript — flexible, but unsafe.

### ⚠️ Why You Should Avoid `any`:

```typescript
function calculateTax(price: any) {
  return price * 0.1; // 💥 What if `price` is a string?
}
```

TypeScript won't complain, but this could crash at runtime.

### ✅ Safer Alternative: Use `unknown`

```typescript
let input: unknown = "Text";
if (typeof input === "string") {
  console.log(input.toUpperCase());
}
```

---

## 4️⃣ Function Parameters with Annotations

**Definition:** Functions can have typed parameters and return types to ensure correct usage.

### ✅ Syntax:

```typescript
function functionName(param1: Type, param2: Type): ReturnType {}
```

### 🧪 Example 1: Typed Parameters and Return

```typescript
function add(x: number, y: number): number {
  return x + y;
}
```

If someone tries to call this incorrectly:

```typescript
add(5, "ten"); // ❌ Error: Argument of type 'string' is not assignable to 'number'
```

### 🧪 Example 2: Optional Parameters

```typescript
function greet(name: string, title?: string): string {
  return title ? `Hello, ${title} ${name}` : `Hello, ${name}`;
}
```

### 🧪 Example 3: Default Parameters

```typescript
function calculateTotal(price: number, tax: number = 0.05): number {
  return price + price * tax;
}
```

### 🧪 Example 4: Arrow Functions with Types

```typescript
const multiply = (a: number, b: number): number => a * b;
```

---

## 5️⃣ The `void` Type: When Functions Don’t Return Anything

**Definition:** The `void` type is used when a function **does not return a value**.

```typescript
function logInfo(message: string): void {
  console.log("INFO:", message);
}
```

### ✅ Use Cases:

* Logging
    
* Event handlers
    
* Side-effect functions
    

### ❌ Invalid Return:

```typescript
function sayHello(): void {
  return "Hello"; // ❌ Error: Type 'string' is not assignable to type 'void'
}
```

### 🧪 `void` in Callbacks

```typescript
function handleClick(callback: () => void) {
  callback();
}

handleClick(() => {
  console.log("Button clicked!");
});
```

---

## 📚 Bonus Tips

### 🔄 Type Aliases

You can create custom types using aliases:

```typescript
type User = {
  id: number;
  name: string;
};

let admin: User = { id: 1, name: "Admin" };
```

### 📏 Literal Types

Restrict a value to specific strings or numbers:

```typescript
let direction: "up" | "down" = "up";
direction = "down"; // ✅
direction = "left"; // ❌ Error
```

---

## 📌 Recap Table

| Concept | Purpose | Example Syntax |
| --- | --- | --- |
| **Type Annotations** | Declare specific types | `let age: number = 25;` |
| **Type Inference** | TypeScript guesses the type | `let name = "John";` |
| `any` Type | Disable type checking | `let data: any = "hello";` |
| **Function Typing** | Annotate params & return values | `function greet(name: string): string {}` |
| `void` Type | Used when function returns nothing | `function log(msg: string): void {}` |

---

## 🧠 Final Thoughts

TypeScript helps you write **robust**, **readable**, and **maintainable** code. By understanding how to use annotations, inference, and function types properly, you’ll prevent bugs before they happen and make your codebase easier to work with.

### ✅ Takeaways:

* Be **explicit** with types where necessary
    
* Leverage **inference** to reduce boilerplate
    
* Avoid `any` — prefer `unknown` or proper types
    
* Type your **function signatures**
    
* Use `void` for functions that don’t return anything
