{"slug": "typescript-types-demystified-simple-types-special-types-and-type-inference", "title": "TypeScript Types Demystified: Simple Types, Special Types, and Type Inference", "summary": "A developer explains TypeScript's type system, covering basic types, type inference, arrays, tuples, union types, and special types like any, unknown, never, and void. The post emphasizes letting TypeScript infer types for local variables while being explicit for function parameters and return types.", "body_md": "*In the first post, we covered why TypeScript exists and how to write your first program. Now it's time to get comfortable with the type system itself — the foundation everything else is built on.*\n\nBy the end of this post, you'll know how to type variables, arrays, and function parameters correctly. You'll also understand the \"special\" types that trip up most beginners: `any`\n\n, `unknown`\n\n, `never`\n\n, and `void`\n\n.\n\nTypeScript's basic types map directly to JavaScript's primitives:\n\n``` js\n// string\nlet firstName: string = \"Ramesh\";\nlet greeting: string = `Hello, ${firstName}`;\n\n// number (no separate int/float — it's all number)\nlet age: number = 31;\nlet price: number = 9.99;\nlet hex: number = 0xFF;\n\n// boolean\nlet isLoggedIn: boolean = true;\nlet hasAccess: boolean = false;\n```\n\nThese are the types you'll use most often. Simple, predictable, and exactly what you'd expect.\n\nYou don't always have to write the type. TypeScript **infers** it from the value you assign:\n\n``` js\nlet city = \"Chennai\";    // TypeScript infers: string\nlet year = 2026;         // TypeScript infers: number\nlet isActive = true;     // TypeScript infers: boolean\n```\n\nOnce inferred, that type is locked in:\n\n``` js\nlet city = \"Chennai\";\ncity = 42; // ❌ Error: Type 'number' is not assignable to type 'string'\n```\n\n**Rule of thumb:** Let TypeScript infer types for local variables. Write explicit annotations for function parameters and return types.\n\n``` js\n// Let inference work for variables\nconst scores = [95, 87, 72]; // inferred as number[]\n\n// Be explicit for function signatures\nfunction calculateAverage(scores: number[]): number {\n  return scores.reduce((a, b) => a + b, 0) / scores.length;\n}\n// ✅ Explicit annotation — good for function params & return types\nfunction formatName(first: string, last: string): string {\n  return `${first} ${last}`;\n}\n\n// ✅ Inferred — good for simple variable assignments\nconst result = formatName(\"Ramesh\", \"Kumar\"); // inferred as string\n\n// ❌ Over-annotating — redundant when value makes it obvious\nconst count: number = 5; // The `= 5` already tells TypeScript it's a number\n```\n\n**Arrays** hold multiple values of the same type:\n\n``` js\n// Two equivalent syntaxes\nlet tags: string[] = [\"typescript\", \"javascript\", \"react\"];\nlet scores: Array<number> = [95, 87, 72];\n\n// TypeScript will catch wrong types in arrays\ntags.push(42); // ❌ Error: Argument of type 'number' is not assignable to type 'string'\n```\n\n**Tuples** are fixed-length arrays where each position has a specific type:\n\n``` js\n// A tuple: exactly [string, number]\nlet user: [string, number] = [\"Ramesh\", 31];\n\n// Order and types are both enforced\nlet wrongOrder: [string, number] = [31, \"Ramesh\"]; // ❌ Error\n\n// Accessing tuple elements\nconsole.log(user[0]); // \"Ramesh\" — TypeScript knows this is string\nconsole.log(user[1]); // 31 — TypeScript knows this is number\n```\n\nTuples are great for things like coordinate pairs, key-value pairs, or when returning multiple values from a function:\n\n```\nfunction getMinMax(numbers: number[]): [number, number] {\n  return [Math.min(...numbers), Math.max(...numbers)];\n}\n\nconst [min, max] = getMinMax([3, 1, 7, 2, 9]);\n// min: number, max: number — fully typed!\n```\n\nSometimes a value can legitimately be more than one type. That's what union types handle:\n\n```\n// This function accepts string OR number\nfunction formatId(id: string | number): string {\n  return `ID-${id}`;\n}\n\nformatId(\"abc123\"); // ✅\nformatId(42);       // ✅\nformatId(true);     // ❌ Error: boolean not in the union\n```\n\nUnion types are especially useful for API responses, form inputs, and optional values:\n\n``` js\n// A status that can only be one of these three strings\nlet orderStatus: \"pending\" | \"shipped\" | \"delivered\";\n\norderStatus = \"shipped\";   // ✅\norderStatus = \"cancelled\"; // ❌ Error: not in the union\n\n// A value that might not exist yet\nlet userId: number | null = null;\nuserId = 101; // Fine, it's assigned now\n```\n\n`any`\n\n, `unknown`\n\n, `never`\n\n, `void`\n\nThese four confuse most beginners. Here's each one explained clearly.\n\n`any`\n\n— The Escape Hatch (Use Sparingly)\n`any`\n\nturns off TypeScript's type checking for that value:\n\n``` js\nlet data: any = \"hello\";\ndata = 42;        // Fine\ndata = true;      // Fine\ndata.foo.bar();   // Fine — no error, even if this blows up at runtime!\n```\n\nWhen to use it: Almost never. `any`\n\ndefeats the purpose of TypeScript. It's there as a last resort when migrating old JavaScript code.\n\n```\n// ❌ Overusing any — you've lost all type safety\nfunction processData(input: any): any { ... }\n\n// ✅ Be specific whenever possible\nfunction processData(input: string[]): number { ... }\n```\n\n`unknown`\n\n— The Safe Version of `any`\n\n`unknown`\n\nsays \"this could be anything, but I need to check before I use it\":\n\n``` js\nlet userInput: unknown = getUserInput();\n\n// ❌ Can't use unknown directly\nconsole.log(userInput.toUpperCase()); // Error!\n\n// ✅ Must narrow the type first\nif (typeof userInput === \"string\") {\n  console.log(userInput.toUpperCase()); // Now it's safe\n}\n```\n\n**Prefer unknown over any** when you genuinely don't know the type. It forces you to handle the uncertainty explicitly.\n\n`void`\n\n— Functions That Return Nothing\nUse `void`\n\nwhen a function doesn't return a value:\n\n```\nfunction logMessage(message: string): void {\n  console.log(message);\n  // No return statement needed\n}\n\n// Trying to use the return value of a void function makes no sense\nconst result = logMessage(\"hello\"); // result is void — useless\n```\n\n`never`\n\n— Code That Never Completes\n`never`\n\nrepresents values that never occur. It's used for:\n\n```\n// Always throws — never returns\nfunction throwError(message: string): never {\n  throw new Error(message);\n}\n\n// Exhaustive check — if you add a new status and forget to handle it,\n// TypeScript will error here\nfunction handleStatus(status: \"active\" | \"inactive\"): string {\n  if (status === \"active\") return \"User is active\";\n  if (status === \"inactive\") return \"User is inactive\";\n\n  // This line should be unreachable\n  const _exhaustive: never = status; // ❌ Error if you missed a case\n  return _exhaustive;\n}\n```\n\n`never`\n\nis an advanced concept — don't worry if it doesn't fully click yet. You'll encounter it naturally as you write more TypeScript.\n\n``` js\n// Primitives\nlet name: string = \"Ramesh\";\nlet age: number = 31;\nlet active: boolean = true;\n\n// Arrays\nlet tags: string[] = [\"ts\", \"js\"];\nlet ids: number[] = [1, 2, 3];\n\n// Tuples\nlet point: [number, number] = [10, 20];\n\n// Union\nlet id: string | number = \"abc\";\nlet status: \"on\" | \"off\" = \"on\";\n\n// Special types\nlet anything: any = \"...\";     // Avoid when possible\nlet safeAny: unknown = \"...\";  // Safer — must narrow before use\nfunction log(): void { ... }   // No return value\nfunction fail(): never { throw new Error(); } // Never returns\n```\n\nThe TypeScript type system is deep, but the everyday usage is straightforward. Here's what to take away:\n\n`string`\n\n, `number`\n\n, `boolean`\n\ncover most cases`string[]`\n\nor `Array<string>`\n\n, your choice`any`\n\n`unknown`\n\n`void`\n\n`never`\n\nFound this helpful? Follow for the rest of the series. Questions or corrections? Drop them in the comments.", "url": "https://wpnews.pro/news/typescript-types-demystified-simple-types-special-types-and-type-inference", "canonical_source": "https://dev.to/ramesh_s_a8f0867d239e927c/typescript-types-demystified-simple-types-special-types-and-type-inference-5bf0", "published_at": "2026-06-19 03:22:28+00:00", "updated_at": "2026-06-19 04:00:22.987632+00:00", "lang": "en", "topics": ["developer-tools"], "entities": ["TypeScript", "JavaScript"], "alternates": {"html": "https://wpnews.pro/news/typescript-types-demystified-simple-types-special-types-and-type-inference", "markdown": "https://wpnews.pro/news/typescript-types-demystified-simple-types-special-types-and-type-inference.md", "text": "https://wpnews.pro/news/typescript-types-demystified-simple-types-special-types-and-type-inference.txt", "jsonld": "https://wpnews.pro/news/typescript-types-demystified-simple-types-special-types-and-type-inference.jsonld"}}