TypeScript is a statically typed superset of JavaScript that adds features such as static typing, type inference, and advanced type manipulation. These features help improve code quality, readability, and maintainability.
1. TypeScript is a Superset of JavaScript
TypeScript extends JavaScript by adding static type checking and other language features. JavaScript code can generally be used in TypeScript, which makes it possible to gradually introduce TypeScript into existing projects.
let message = "Hello, TypeScript!";
console.log(message);
2. Static Typing Helps Catch Errors Early
TypeScript checks types during development and reports many type-related errors before the code runs.
let age: number = 25;
// age = "twenty-five";
// Error: Type 'string' is not assignable to type 'number'
This helps catch common type-related mistakes early and makes code easier to maintain.
3. Supports Modern JavaScript Features
TypeScript supports modern JavaScript features such as arrow functions, classes, destructuring, and template literals. Depending on the configured target, TypeScript can transform supported syntax into JavaScript compatible with older environments.
const greet = (name: string): string => `Hello, ${name}!`;
console.log(greet("Alen"));
The JavaScript output depends on the target configured in tsconfig.json.
4. Gradual Adoption is Possible
You don't need to rewrite an entire JavaScript project at once. TypeScript can be introduced gradually, allowing developers to migrate files and add type checking over time.
For example, JavaScript:
let message = "Hello, TypeScript!";
Can be gradually migrated to TypeScript:
let message: string = "Hello, TypeScript!";
TypeScript also provides features such as allowJs and checkJs that can help when working with JavaScript files in a TypeScript project.
5. Type Inference Saves Time
TypeScript can automatically infer variable types from their assigned values, reducing the need to explicitly specify types in many situations.
let name = "Alice"; // TypeScript infers `name` as string
// name = 42;
// Error: Type 'number' is not assignable to type 'string'
Explicit type annotations are still useful when they improve clarity or when the type cannot be inferred as intended.
6. Template Literal Types Create Pattern-Based String Types
Template literal types allow you to construct new string literal types from other types.
type EventName<T extends string> = `${T}Changed`;
type ClickEvent = EventName<"click">;
// "clickChanged"
Here, ClickEvent becomes the string literal type "clickChanged".
Unlike JavaScript template literals, template literal types operate at the type level, not at runtime.
7. The unknown Type Provides Safer Type Checking
The unknown type can represent any value, but unlike any, it requires you to perform appropriate type checks before performing most operations on the value.
let data: unknown = "Hello";
if (typeof data === "string") {
console.log(data.toUpperCase()); // Safe
}
This makes unknown useful when the type of a value is not known in advance, such as data received from an external source.
8. The never Type Represents Values That Never Occur
The never type represents values that never occur. It is commonly used for functions that never successfully complete, such as functions that always throw an error.
function throwError(message: string): never {
throw new Error(message);
}
Since this function always throws an error, it never returns normally.
9. Conditional Types Apply Type-Level Conditions
Conditional types allow you to choose one type or another based on a type relationship.
type IsString<T> = T extends string ? true : false;
type A = IsString<"hello">; // true
type B = IsString<42>; // false
Here, T extends string ? true : false works similarly to a conditional expression, but it operates at the type level.
10. TypeScript Improves Code Maintainability
TypeScript's static type system can make large codebases easier to understand and maintain by providing type checking, better editor support, and safer refactoring.
function calculateTotal(price: number, quantity: number): number {
return price * quantity;
}
console.log(calculateTotal(100, 2)); // 200
If an incorrect argument type is passed, TypeScript can identify the problem during development.