Typescritp được thừa hưởng cả lập trình hướng hàm (function oriented programming) và hướng đối tượng (object oriented programming) nên nó có cú pháp tương đối linh hoạt. Trong bài này Dũng sẽ cùng các bạn đi tìm hiểu một số cú pháp của Typescript nhé.

Khai báo một hàm

Cái này thì quá đơn giản rồi, ví dụ chúng ta có thể khai báo một hàm sum như sau:

function sum(a: number, b: number) {
    return a + b;
}

Ở đây chúng ta có từ khoá function và các tham số sẽ được quy định kiểu.

Khai báo một lớp

Như trong bài trước chúng ta đã thấy chúng ta có thể sử dụng từ khoá class để tạo một lớp như thế này:

class Greeter {
    private greeting: string;

    constructor(greeting: string) {
        this.greeting = greeting;
    }

    public greet(person: Person): string {
        return `${this.greeting}, ${person.firstName} ${person.lastName}!`;
    }
}

Hàm tạo của lớp sẽ có tên constructor, các trường, hàm chúng ta có thể sử dụng các từ khoá private, protected, public để quy định phạm vi truy cập. Tuy nhiên nó chỉ có ý nghĩa đối với typescript thôi, còn khi biên dịch ra mã javascript thì mặc định tất cả đều là public thế này:

class Greeter {
    constructor(greeting) {
        this.greeting = greeting;
    }
    greet(person) {
        return `${this.greeting}, ${person.firstName} ${person.lastName}!`;
    }
}

Thừa kế một lớp

Cũng tương tụ như các ngôn ngữ hướng đối tượng, Typescript cũng hỗ trợ abstract và thừa kế, ví dụ như sau:

abstract class Animal {
    public abstract getName(): string;
}

class Cat extends Animal {

    public getName(): string {
        return "Cat";
    }
}

let animal = new Cat();
console.log(animal.getName());

Trong ví dụ này chúng ta khởi tạo một lớp trừu tượng là Animal đại diện cho động vật với hàm getName chưa được cài đặt. Sau đó chúng ta khai báo một lớp Cat đại diện cho một loại động vật củ thể là con mèo và chúng ta lúc này mới cài đặt hàm getName.

Cài đặt interface

Chúng ta có thể khai báo một interface cho công việc tính toán như sau:

interface Calculator {

    calculate(a: number, b: number): number;
} 

Sau đó chúng ta có thể cài đặt một lớp tính toán cụ thể chăng hạn như tính tổng như sau:

interface Calculator {

    calculate(a: number, b: number): number;
}

class SumCalculator implements Calculator {

    calculate(a: number, b: number): number {
        return a + b;
    }
}

let calculator = new SumCalculator();
console.log("caculated:", calculator.calculate(2, 3));

Generics

Genereics là một tính năng không thể thiểu trong lập trình hướng đối tượng, nó giúp chúng ta common hoá được rất nhiều việc cho các loại đối tượng khác nhau, chính vì thế mà TypeScript cũng cung cấp cho chúng ta các cú pháp cho Generics.
Chúng ta có thể sử dụng Generics với lớp thế này:

class Wrapper<T> {
    
    private value: T | undefined = undefined;
    
    public setValue(value: T) {
        this.value = value;
    }

    public getValue(): T {
        return this.value!;
    }
}

let personWrapper = new Wrapper<Person>();
personWrapper.setValue(person);
console.log(personWrapper.getValue())

Hay với hàm thế này:

class Value {
    private value: any;

    constructor(value: any) {
        this.value = value;
    }

    public cast<T>(): T {
        return this.value as T;
    }
}

let value = new Value("Hello TechMaster");
console.log(value.cast<string>());

Typescript cũng đã cung cấp sẵn cho chúng ta một số lớp như Array, Set, Map, và chúng ta có thể sử dụng như sau:

let stringArray = new Array<string>();
let stringSet = new Set<string>();
let valueByKey = new Map<string, string>();

Stream

Typescript cung cấp cho chúng ta một số phương thức để lặp qua các phần tử trong 1 danh sách khá tiện, ví dụ chúng ta muốn lọc và lấy ra danh sách firstName của các persons, chúng ta có thể làm như sau:

let personArray = new Array<Person>();
personArray.push({
    firstName: "Tech",
    lastName: "Master"
});
personArray.push({
    firstName: "Hello",
    lastName: "World"
});
let filteredFirstName = personArray
    .filter(person => person.firstName == "Tech")
    .map(person => person.firstName);

Chúng ta có thể sử dụng hàm forEach tương tự như javascript bình thường:

filteredFirstName.forEach((person) => {
    console.log("person first name in for each", person);
});

Hay sử dụng hàm reduce để tính tổng:

let numberArray = Array(1, 2, 3);
let reduceSum = numberArray.reduce((total, item) => total + item, 0);
console.log("reduce sum:", reduceSum);

Async/Await

Cũng giống javascript thông thường, typescript cũng cung cấp cho chúng ta cú pháp cho lập trình bất đồng bộ với async/await ví dụ như sau:

function divideByPromise(a: number, b: number): Promise<number> {
    return new Promise((resolve, reject) => {
        if (b != 0) {
            resolve(a / b);
        } else {
            reject("can not divide ZERO");
        }
    })
}

async function sumAndDeivide(a: number, b: number, c: number) {
    const sumAB = a + b;
    const answer = await divideByPromise(sumAB, c);
    return answer;
}

async function main() {
    const sumAndDeivideAnswer = await sumAndDeivide(2, 4, 2);
    console.log("sumAndDeivideAnswer:", sumAndDeivideAnswer);
    await sumAndDeivide(2, 4, 0);
}

main();

Tổng kết

Như vậy chúng ta đã cùng nhau tìm hiểu một số cú pháp cơ bản của typescript để sử dụng cho các bài kế tiếp.


Cám ơn bạn đã quan tâm đến bài viết|video này. Để nhận được thêm các kiến thức bổ ích bạn có thể:

  1. Đọc các bài viết của TechMaster trên facebook: https://www.facebook.com/techmastervn
  2. Xem các video của TechMaster qua Youtube: https://www.youtube.com/@TechMasterVietnam nếu bạn thấy video/bài viết hay bạn có thể theo dõi kênh của TechMaster để nhận được thông báo về các video mới nhất nhé.
  3. Chat với techmaster qua Discord: https://discord.gg/yQjRTFXb7a