β¨ 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:
Type Annotations
Type Inference
The
anyTypeFunction Parameters with Annotations
The
voidReturn 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
let name: string = "Alice";
let age: number = 28;
let isLoggedIn: boolean = true;
Here, you're telling TypeScript:
namemust always be a stringagemust be a numberisLoggedInmust be a boolean
β Error Example:
name = 42; // Error: Type 'number' is not assignable to type 'string'
π§ͺ Example 2: Array and Object Annotations
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:
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
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:
language.toUpperCase(); // IntelliSense knows it's a string!
version.toFixed(1); // Works because it's inferred as number
π§ͺ Example 2: No Initialization
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!β
let mysteryData: any = "Text";
mysteryData = 42;
mysteryData = true;
It behaves like JavaScript β flexible, but unsafe.
β οΈ Why You Should Avoid any:
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
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:
function functionName(param1: Type, param2: Type): ReturnType {}
π§ͺ Example 1: Typed Parameters and Return
function add(x: number, y: number): number {
return x + y;
}
If someone tries to call this incorrectly:
add(5, "ten"); // β Error: Argument of type 'string' is not assignable to 'number'
π§ͺ Example 2: Optional Parameters
function greet(name: string, title?: string): string {
return title ? `Hello, ${title} ${name}` : `Hello, ${name}`;
}
π§ͺ Example 3: Default Parameters
function calculateTotal(price: number, tax: number = 0.05): number {
return price + price * tax;
}
π§ͺ Example 4: Arrow Functions with Types
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.
function logInfo(message: string): void {
console.log("INFO:", message);
}
β Use Cases:
Logging
Event handlers
Side-effect functions
β Invalid Return:
function sayHello(): void {
return "Hello"; // β Error: Type 'string' is not assignable to type 'void'
}
π§ͺ void in Callbacks
function handleClick(callback: () => void) {
callback();
}
handleClick(() => {
console.log("Button clicked!");
});
π Bonus Tips
π Type Aliases
You can create custom types using aliases:
type User = {
id: number;
name: string;
};
let admin: User = { id: 1, name: "Admin" };
π Literal Types
Restrict a value to specific strings or numbers:
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β preferunknownor proper typesType your function signatures
Use
voidfor functions that donβt return anything


