iTranslated by AI
Learning the Basic Concepts of TypeScript
Introduction
TypeScript is a language that adds a type system to JavaScript, providing static typing and powerful tool support. In this article, we will learn about the basic concepts of TypeScript and explore its benefits.
Type System
TypeScript's type system detects errors at compile time and improves code quality.
Type Annotations
let message: string = "Hello, TypeScript";
console.log(message);
In this code, the string type is specified for the message variable.
Benefits of the Type System
-
Early Error Detection: Errors such as type mismatches can be detected at compile time, allowing bugs to be found early.
-
Self-Documenting Code: By adding type annotations, the intent of the code becomes clear, making it easier for other developers to understand.
-
IDE Support: Based on type information, IDEs provide better completion and refactoring assistance.
Interfaces
In TypeScript, you can use interfaces to define the shape of an object. This allows for structural typing.
interface Person {
name: string;
age: number;
}
function greet(person: Person) {
return `Hello, ${person.name}`;
}
let user = { name: "John", age: 30 };
console.log(greet(user));
In this code, we define a Person interface and create a greet function that takes an object conforming to that shape as an argument.
Benefits of Interfaces
-
Code Consistency: Using interfaces allows you to manage the structure of objects consistently.
-
Code Reusability: By using interfaces, you can reuse functions or classes that handle different objects sharing a common structure.
-
Clear Contracts: Interfaces define clear contracts between pieces of code, preventing misuse.
Type Aliases
Type aliases allow you to express complex type definitions concisely.
type StringOrNumber = string | number;
function print(value: StringOrNumber) {
console.log(value);
}
print("Hello");
print(42);
In this code, we define a StringOrNumber type alias and create a print function that accepts values of type string or number.
Benefits of Type Aliases
-
Improved Readability: By expressing complex type definitions concisely, the readability of the code is improved.
-
Reusability: Using type aliases allows you to reuse the same type definition in multiple locations.
Generics
In TypeScript, you can use generics to create versatile functions and classes. Generics make it easier to reuse code that handles different types.
function identity<T>(arg: T): T {
return arg;
}
console.log(identity<string>("Hello"));
console.log(identity<number>(42));
In this code, we define a generic function identity that can accept any type T.
Benefits of Generics
-
Code Reusability: By using generics, you can reuse the same logic for different types.
-
Type Safety: Using generics allows you to write type-safe code, which helps prevent runtime errors.
-
Code Conciseness: By using generics, you no longer need to define multiple functions or classes to perform the same process, keeping the code concise.
Asynchronous Processing and Promises
TypeScript supports Promises for handling asynchronous processing. Additionally, by using the async / await syntax, you can write asynchronous code as if it were synchronous.
Promise
function delay(ms: number): Promise<void> {
return new Promise((resolve) => setTimeout(resolve, ms));
}
delay(1000).then(() => console.log("1 second later"));
In this code, the delay function returns a Promise that waits for the specified amount of time.
async / await
async function asyncDelay() {
await delay(1000);
console.log("1 second later");
}
asyncDelay();
In this code, async / await is used to write asynchronous processing synchronously.
Benefits of Asynchronous Processing
-
Simplification of Asynchronous Operations: By using Promises and
async/await, you can write asynchronous operations simply. -
Improved Code Readability: Using
async/awaithelps avoid callback hell, improving code readability. -
Unified Error Handling: Errors in asynchronous processing can be handled uniformly using the
try/catchsyntax.
Decorators
function log(target: any, propertyKey: string, descriptor: PropertyDescriptor) {
const originalMethod = descriptor.value;
descriptor.value = function (...args: any[]) {
console.log(`Calling ${propertyKey} with arguments:`, args);
return originalMethod.apply(this, args);
};
}
class Calculator {
@log
add(a: number, b: number): number {
return a + b;
}
}
const calc = new Calculator();
console.log(calc.add(2, 3));
In this code, the log decorator is used to log the calls to the add method.
Benefits of Decorators
-
Code Modularization: Using decorators allows you to separate cross-cutting concerns and modularize your code.
-
Improved Reusability: By using decorators, you can apply the same behavior to multiple classes or methods.
-
Code Conciseness: Decorators allow you to describe additional behaviors concisely.
Type Guards
In TypeScript, you can use type guards to check types at runtime and perform appropriate processing.
function isString(value: any): value is string {
return typeof value === "string";
}
function printValue(value: string | number) {
if (isString(value)) {
console.log(`String: ${value}`);
} else {
console.log(`Number: ${value}`);
}
}
printValue("Hello");
printValue(42);
In this code, the isString type guard is used to check whether value is of type string.
Benefits of Type Guards
-
Safe Type Conversion: By using type guards, you can safely perform type conversions at runtime.
-
Improved Code Readability: Using type guards allows you to clearly describe processing based on conditions.
-
Enhanced Type Safety: Using type guards helps prevent unintended type errors.
Mapped Types
Using TypeScript's mapped types, you can create new types based on existing ones. This is extremely useful when transforming the properties of an object.
type Person = {
name: string;
age: number;
};
type ReadonlyPerson = Readonly<Person>;
const person: ReadonlyPerson = {
name: "John",
age: 30,
};
// person.age = 31; // Error: 'age' is a read-only property
Benefits of Mapped Types
-
Simplification of Type Transformation: Mapped types make it easy to create new types from existing ones.
-
Enhanced Type Safety: Using mapped types ensures that type transformations are performed in a type-safe manner, preventing unintended type errors.
Union Types and Intersection Types
TypeScript allows you to combine multiple types using union types and intersection types.
Union Types
function format(value: string | number) {
if (typeof value === "string") {
return value.toUpperCase();
} else {
return value.toFixed(2);
}
}
console.log(format("hello"));
console.log(format(42));
In this code, the format function accepts an argument of type string or number.
Intersection Types
type Person = {
name: string;
};
type Employee = {
id: number;
};
type EmployeePerson = Person & Employee;
const employee: EmployeePerson = {
name: "John",
id: 1,
};
console.log(employee);
In this code, we create an EmployeePerson type that combines the Person and Employee types.
Benefits of Union and Intersection Types
-
Flexible Type Definitions: You can define types flexibly by using union types and intersection types.
-
Enhanced Type Safety: Combining types in a type-safe manner helps prevent unintended type errors.
Summary
I usually use Java, but I thought TS is better because it allows for more granular type definitions.
Discussion