Bí kíp chú thích hàm trong Typescript: từ cơ bản đến nâng cao

0 0 0

Người đăng: Vũ Tuấn

Theo Viblo Asia

TypeScript là ngôn ngữ lập trình ngày càng phổ biến, đặc biệt trong phát triển web. Bài viết này sẽ hướng dẫn bạn cách chú thích hàm trong TypeScript, từ những kiến thức cơ bản đến các kỹ thuật nâng cao như generic và interface.

Cách cơ bản nhất để chú thích một hàm trong TypeScript là như sau:

function add(a: number, b: number): number{ // logic
} // or const add = (a: number, b: number): number => { //logic
}

Các tham số tùy chọn được chú thích bằng dấu hỏi chấm param? như sau:

function optional(a: number, b?: number){ console.log(a)
}

Nhưng còn các hàm callback, hoặc các hàm mà kiểu của đối số và kiểu trả về có liên quan (trong trường hợp đó, là generic) thì sao?

Giá trị hàm

Hãy quan sát hàm JavaScript này:

function multiplier(factor){ return value => factor * value
}

Vì vậy, chúng ta có thể sử dụng hàm như sau:

const n = multiplier(6)
n(8) // 48

Giá trị hàm được chú thích trong TypeScript như sau:

(param1: type, param2: type)=> type // or const add: (a: number, b: number)=> number = function (a, b){ return a + b
}

Vì vậy, để chú thích hàm multiplier, chúng ta có:

function multiplier(factor: number): (value: number) => number{ return value => factor * value
}

IDE của bạn (tốt nhất là VSCode) sẽ tự động suy ra kiểu của value (là number) trong logic hàm.

Hàm Generic

Chú thích hàm này là sai:

function pickFirst(array: Array<T>): T{ return array[0]
}

Đương nhiên, điều này gây ra lỗi:

"Cannot find name T"

Do đó, định dạng chú thích các hàm generic là:

function fnName <T,U>(param: T): U{ //logic
}

Hãy quan sát vị trí khai báo tên generic. Vì vậy, để chú thích chính xác hàm trên:

function pickFirst<T>(array: Array<T>): T{ return array[0]
}

Bây giờ nó hoạt động.

Nhưng còn các hàm Generic có tham số hàm thì sao?

Ví dụ: chúng ta muốn chú thích một hàm map tùy chỉnh có tên myMap được viết như sau trong Javascript:

function myMap(arr, fn){ rreturn arr.map(fn)
}

Chúng ta có thể chú thích nó như sau:

function myMap<Input, Output>(arr: Input[], fn: (item: Input, index?: number) => Output): Output[]{ return arr.map(fn)
}

Điều chúng ta cần lưu ý trong đoạn mã trên là hàm fn nhận một mục cùng kiểu với mảng Input và trả về một kiểu Output.

Còn phương thức tĩnh Array.from() thì sao?

function myFrom<Type>(iterable: Iterable<Type>): Array<Type>{ // logic
}

Hoặc phương thức array.filter()?

function myFilter<Input>(arr: Input[], fn: (item: Input) => boolean): Input[]{ return arr.filter(fn)
}

Ràng buộc Generic

Bạn cũng có thể ràng buộc các biến generic với các kiểu có một thuộc tính cụ thể. Ví dụ:

function pickInnerFirst<T extends {length: number}>(array: Array<T>): T{ return array[0][0]
}

Hàm này chọn phần tử đầu tiên trong một mảng hai chiều.

Điều này đảm bảo rằng nó chỉ hoạt động cho mảng và chuỗi (chủ yếu) theo cách mà:

pickOne([12, 20, 30]) // wont work.

Chúng ta cũng có thể sử dụng interface:

interface Lengthly{ length: number;
} function pickInnerFirst<T extends Lengthly>(array: Array<T>): T{ return array[0][0]
}

Interface Hàm

Trong trường hợp bạn chưa biết, hàm là các đối tượng và chúng có các thuộc tính:

const add = (a, b) => a + b console.log(add.toString()) //(a, b) => a + b // also
console.log(Object.getPrototypeOf(add) == Function.prototype) //true
console.log(Object.getPrototypeOf(Function.prototype) == Object.prototype) //true

Ví dụ thứ hai chỉ ra rằng hàm add là con của Object.prototype (mặc dù nó không phải là con trực tiếp) và do đó là một đối tượng.

Điều thú vị là, bạn có thể gắn các thuộc tính vào một hàm trong JavaScript:

function shout(fn, value){ fn(value) console.log(fn.description)
} function hey(value){ console.log(value)
} hey.description = `A function called ${hey.name}` // A shout(hey, "Hola!!!")

Đoạn mã này sẽ trả về:

>> Hola!!!
>> A function called hey

Hãy quan sát rằng tại A, chúng ta đã gắn một thuộc tính có tên description vào hàm, điều này chỉ có thể thực hiện được với các đối tượng.

Điều đó để kết luận rằng: các đối tượng có thể được mô tả bằng interface (thông thường). Đối với các hàm, điều này cũng có thể thực hiện được. Tuy nhiên, đó chỉ là điều bạn nên cân nhắc khi bạn đang thêm các thuộc tính đặc biệt vào các hàm của mình.

interface describableFunction{ (value: string): void; //A description: string;
}

Tại chú thích A là nơi chúng ta mô tả các đối số và kiểu trả về của hàm.

Vì vậy, để chú thích mã trước đó trong TypeScript:

interface describableFunction{ (value: string): void; description: string;
} function shout(fn: describableFunction, value: string) { //A fn(value) console.log(fn.description)
} function hey(value: string) { console.log(value)
} hey.description = `A function called ${hey.name}`
shout(hey, "Hola!!!")

Hãy quan sát cách chúng ta sử dụng interface trong hàm shout tại A.

Tại sao bạn nên hiểu cách chú thích hàm trong TypeScript?

Việc chú thích hàm trong TypeScript giúp xây dựng một hệ thống kiểu thông minh hơn, từ đó giảm khả năng xảy ra lỗi. Nếu bạn đang xây dựng một thư viện hoặc framework, bạn có thể phải sử dụng một số hoặc hầu hết các khái niệm được đề cập ở đây. Nếu bạn chỉ đang sử dụng thư viện, những khái niệm này không thực sự cần thiết, mặc dù chúng có thể giúp bạn hiểu sâu hơn về các thư viện bạn đang làm việc.

Cảm ơn các bạn đã theo dõi!

Bình luận

Bài viết tương tự

- vừa được xem lúc

Giới thiệu Typescript - Sự khác nhau giữa Typescript và Javascript

Typescript là gì. TypeScript là một ngôn ngữ giúp cung cấp quy mô lớn hơn so với JavaScript.

0 0 528

- vừa được xem lúc

Type annotation vs Type Inference - Typescript

Trong bài viết này, chúng ta sẽ tìm hiểu kỹ về TypeScript bằng cách tìm hiểu sự khác biệt giữa kiểu chú thích và kiểu suy luận. Tôi sẽ cho rằng bạn có một số kinh nghiệm về JavaScript và biết về các kiểu cơ bản, như chuỗi, số và boolean.

0 0 45

- vừa được xem lúc

Type Annotation và Type Inference trong TypeScript là gì?

Khi làm việc với javascript chắc hẳn các bạn đã quá quen với việc dùng biến mà không cần phải quan tâm đến kiểu dữ liệu của nó là gì phải không? Đúng là mới đầu tiếp cận với Typescript mình cũng cảm thấy nó khá là phiền vì cần phải khai báo đủ type để nó chặt chẽ hơn. Lúc đó mình còn nghĩ: " JavaScr

0 0 37

- vừa được xem lúc

Tìm hiểu TypeScript và kiến thức cơ bản

TypeScript là gì. TypeScript sử dụng tất cả các tính năng của của ECMAScript 2015 (ES6) như classes, modules.

0 0 53

- vừa được xem lúc

TypeScript - P1: Vì sao TypeScript được yêu thích đến vậy?

Trải nghiệm thực tế. Trước khi là một Web Developer, tôi là một Mobile Developer và Java là thứ mà tôi từng theo đuổi.

0 1 69

- vừa được xem lúc

4 Tính năng rất hay từ TypeScript

Xin chào các bạn hôm nay mình xin chia sẽ những tính năng rất hay của TypeScript (TS), các bạn cùng tìm hiểu nhé. Ngoài việc set Type cho biến, tham số hay function thì ví dụ khi bạn nhìn vào một tham

0 0 96