💯 Day 01 - Overview TypeScript - Part 01
date
Mar 1, 2023
slug
day-01-overview-typescript
status
Published
tags
Study
TypeScript
summary
Ngày 01, tìm hiểu TypeScript là gì, có cái nhìn tổng quát về TypeScript
type
Post
Bữa nay sẽ là ngày đầu tiên trong thử thách 100 Days of Code
Mình sẽ tìm hiểu TypeScript trước tiên, vì mục tiêu hướng đến ban đầu là code JS nhưng vẫn phải có Type Hint rõ ràng, có các ràng buộc về kiểu dữ liệu. Trước đây mình code PHP ≤ 7.4 tự do quá, không thích thế nữa, chuyển sang 8.1 dù ít dù nhiều cảm thấy ổn áp hơn. Bây giờ code JS cũng muốn như vậy, TypeScript quá toẹt zời, mình thấy tiếc trước đây không biết tới nó sớm hơn.
Đọc toàn bộ Documents để hình dung cơ bản về TS, làm sao để khai báo kiểu dữ liệu,
+ Type Alias là gì - là 1 cái tên cho tất cả mọi loại type
+ Interface là gì - Hiểu nôm na thì nó cũng là cách để đặt tên cho tất cả mọi loại type
⇒ 2 cái này về cơ bản là giông nhau, toàn bộ tính chất của TA ⇒ Interface đều có
⇒ Khác biệt chính là Interface có thể kế thừa và chỉnh sửa các property dễ dàng
+ Type Assertions - Nó giống như 1 lời khẳng định rằng chúng ta biết rõ hàm này sẽ trả về 1 type cụ thể nào đó
const myCanvas = document.getElementById("main_canvas") as HTMLCanvasElement; //You can also use the angle-bracket syntax (except if the code is in a .tsx file), which is equivalent: const myCanvas = <HTMLCanvasElement>document.getElementById("main_canvas");
+ Literal Types - Theo cách hiểu đơn giản của mình, nó giống như ép kiểu, bắt buộc dữ liêu so sánh phải BẰNG type khai báo ban đầu
- Có thể hiểu 1 variable được khai báo với keyword const cũng là 1 Literal Type vì nó không giống như let hay var cho phép ĐẠI DIỆN/THAY ĐỔI giá trị khác nhau
- Nó như khai báo dữ liệu có kiểu ENUM ấy :”)))~
Ngoài các loại Primary Types: string, number, boolean thì có thêm bigint, symbol
- Symbol tạo ra THAM CHIẾU DUY NHẤT (Unique Referance)
const firstName = Symbol("name"); const secondName = Symbol("name"); if (firstName === secondName) { This condition will always return 'false' since the types 'typeof firstName' and 'typeof secondName' have no overlap. // Can't ever happen }
+ Function Type Expressions
function greeter(fn: (a: string) => void) { fn("Hello, World"); } function printToConsole(s: string) { console.log(s); } greeter(printToConsole);
Đoạn cú pháp (a: string) => void có nghĩa là: 1 function với 1 tham số là a, có type là string và function này không trả về giá trị nào
Hoặc có thể dùng Type Alias để đặt tên cho function type:
type GreetFunction = (a: string) => void; function greeter(fn: GreetFunction) { // ... }
+ Call Signatures - Trong JS function có các thuộc tính có thể gọi (callable) được. Function Type Express không hỗ trợ việc này, để mô tả thứ gì đó có thể gọi được từ thuộc tính, chúng ta có thể định nghĩa 1 Call signature trong 1 object type như sau:
type DescribableFunction = { description: string; (someArg: number): boolean; }; function doSomething(fn: DescribableFunction) { console.log(fn.description + " returned " + fn(6)); } // Note that the syntax is slightly different compared to a function type expression - use : between the parameter list and the return type rather than =>.
+ Construct Signatures - JS fucntion cũng có thể được invoked với keyword/operator
new
. TS thì đề cập nó giống như constructors
bởi vì nó thường dùng để tạo mới object. Chúng ta có thể định nghĩa 1
contruct signature
bằng cách thêm từ khoá new vào trước 1 call signature như thế này:type SomeConstructor = { new (s: string): SomeObject; }; function fn(ctor: SomeConstructor) { return new ctor("hello"); }
Cũng có cách khác để biến nó có thể gọi được với hoặc không cần keyword
new
:interface CallOrConstruct { new (s: string): Date; (n?: number): number; }
+ Generic Functions - Phần này quan trọng và mình cũng đang lơ mơ khó hiểu :”)))~
Trong TS
generics
được sử dụng khi chúng ta muốn mô tả một dự tương đổi (correspondence) giữa 2 giá trị. Chúng ta làm điều này bằng cách định nghĩa type parameter (Type
) vào function signature.function firstElement<Type>(arr: Type[]): Type | undefined { return arr[0]; }
Bằng cách thêm vào 1 type parameter
Type
vào function này và sử dụng nó ở 2 nơi, chúng ta tạo 1 liên kết giữa input
của function và output
, như vậy khi chúng gọi nó, IDE sẽ mô tả rõ type cho chúng ta thấy:// s is of type 'string' const s = firstElement(["a", "b", "c"]); // function firstElement<string>(arr: string[]): string | undefined // n is of type 'number' const n = firstElement([1, 2, 3]); // function firstElement<number>(arr: number[]): number | undefined // u is of type undefined const u = firstElement([]); // function firstElement<never>(arr: never[]): undefined
Note that we didn’t have to specify
Type
in this sample. The type was inferred - chosen automatically - by TypeScript.We can use multiple type parameters as well. For example, a standalone version of
map
would look like this:function map<Input, Output>(arr: Input[], func: (arg: Input) => Output): Output[] { return arr.map(func); } // Parameter 'n' is of type 'string' // 'parsed' is of type 'number[]' const parsed = map(["1", "2", "3"], (n) => parseInt(n));
TS có thể tự suy luận type của
Input
từ mảng string
đầu vào, tương tự với Output
dựa trên giá trị trả về của hàm (number
)