Getting Started With React and TypeScript Pt.4 – Tips on Getting Started

https://blog.alexdevero.com/react-and-typescript-pt4/

Take it slowly

Khi bạn mới bắt đầu với React và TypeScript, hãy từ từ. Bạn có thể muốn bật tất cả các quy tắc được đề xuất trong tsconfig của mình. Điều này có thể hiệu quả đối với một số người. Đối với những người khác, nó hoàn toàn không hoạt động. Sử dụng tất cả các quy tắc được đề xuất có thể giúp bạn học cách làm việc với React và TypeScript nhanh hơn.

Điều này đặc biệt đúng khi bạn bắt đầu chơi với React và TypeScript trong một dự án mới. Khi bạn bắt đầu xây dựng một thứ gì đó từ đầu, với mục đích học và thực hành làm việc với React và TypeScript. Trong trường hợp đó, không có gì có thể phá vỡ. Mặt khác, nếu bạn làm điều này trong một dự án hiện có thì sao?

Trong một dự án hiện tại, rất nhiều thứ có thể bị phá vỡ. Khi tôi bắt đầu với TypeScript, tôi quyết định triển khai TypeScript trong một trong những dự án của mình. Đó là một dự án nhỏ. Điều đó không thành vấn đề. Dự án nhỏ hay không, tôi vẫn mất vài ngày trước khi có thể khắc phục tất cả các vấn đề, theo cấu hình TypeScript được đề xuất.

Đúng vậy, nó đã giúp tôi học rất nhiều thứ nhanh hơn, nhanh hơn rất nhiều. Đây là điều mà học “cách khó” làm rất tốt. Tuy nhiên, cũng cần rất nhiều kiên nhẫn để đi từ bản dựng thất bại này sang bản dựng khác. Điều này có thể gây nản lòng cho nhiều người. Nếu điều này không giống như điều bạn muốn trải qua, thì có những cách tiếp cận khác hiệu quả.

Create a “learning” project

Một tùy chọn là tạo dự án mới từ đầu, chỉ nhằm mục đích tìm hiểu về React và TypeScript cũng như cách làm việc với cả hai. Khi bạn bắt đầu lại từ đầu, không có gì có thể phá vỡ. Không có gì có thể gây ra lỗi và cảnh báo bạn sẽ phải sửa trong vài ngày.

Điều này sẽ giúp bạn tiếp cận với React và TypeScript dễ dàng hơn. Một bước tại thời điểm đó, bạn sẽ học cách làm việc với các thành phần, hook và JavaScript theo cách “TypeScript”. Điều này có thể mất nhiều thời gian hơn so với tất cả. Điều đó không quan trọng. Điều quan trọng là sử dụng phương pháp phù hợp với bạn, bất kể thời gian cần thiết.

Disable the strict rule (just for now)

Một tùy chọn khác là thử triển khai TypeScript trong một trong những dự án hiện có của bạn với quy tắc nghiêm ngặt bị tắt. Việc tắt quy tắc này sẽ tắt tất cả các tùy chọn kiểm tra loại nghiêm ngặt. Đó là: --noImplicitAny, --noImplicitThis, --alwaysStrict, --strictBindCallApply, --strictNullChecks, --strictFunctionTypes và --strictPropertyInitialization.

Khi bạn tắt quy tắc này, TypeScript sẽ biên dịch mã của bạn ngay cả khi một trong những kiểm tra kiểu nghiêm ngặt sẽ không vượt qua bài kiểm tra. Nếu bạn sử dụng IDE có hỗ trợ intellisense cho TypeScript, chẳng hạn như VS Code, IDE sẽ vẫn hiển thị cho bạn các vấn đề trong mã của bạn. Một tùy chọn khác, để xem các vấn đề trong mã của bạn, là sử dụng typecript-eslint.

Khi tùy chọn nghiêm ngặt bị vô hiệu hóa, bạn có thể dần dần sửa chữa và chú thích mã của mình nếu cần. Đây sẽ là cách thân thiện hơn để thêm TypeScript vào dự án của bạn, chứ không phải là một cú tát hay cú đấm mạnh vào mặt sau khi bạn khởi động máy chủ nhà phát triển. Khi bạn hoàn tất, đừng quên bật tùy chọn nghiêm ngặt.

Avoid using any

Một số nhà phát triển thích sử dụng bất kỳ loại nào hầu như ở khắp mọi nơi. Điều này được cho là giúp bắt đầu với TypeScript dễ dàng hơn. Đây không phải là một ý kiến ​​hay và chắc chắn không phải là một cách thực hành tốt. Việc sử dụng ngôn ngữ được đánh máy hoặc tập hợp ngôn ngữ đã nhập sẽ có ích lợi gì nếu bạn không sử dụng đúng hệ thống loại của nó?

Một mục đích của việc sử dụng ngôn ngữ đánh máy là sử dụng các kiểu thích hợp để tránh lỗi. Sử dụng bất kỳ đi ngược lại điều này. Khi bạn sử dụng bất kỳ thứ gì có nghĩa là thứ đó có thể thuộc bất kỳ loại nào. Nó có thể là chuỗi, số, boolean, đối tượng, mảng, bất cứ thứ gì. Ngoài ra, sử dụng bất kỳ cho phép thay đổi loại của điều đó.

Ví dụ: giả sử bạn suy luận điều gì đó như bất kỳ thứ gì bạn có thể sau đó gán cho nó một chuỗi. Sau đó, bạn có thể đổi ý và gán số đó. Sau đó một chút, bạn có thể thay đổi quyết định của mình một lần nữa và thay đổi nó thành boolean. Bạn không cần phải bắt đầu sử dụng TypeScript để tạo ra mớ hỗn độn này. JavaScript sẽ là quá đủ để làm điều đó.

Nếu bạn muốn bắt đầu sử dụng TypeScript, bạn cũng nên sử dụng đúng hệ thống loại của nó. Điều này có nghĩa là tránh bất kỳ khi nào bạn có thể, điều này sẽ rất thường xuyên. Có một số tình huống trong đó sử dụng bất kỳ là một tùy chọn. Một tình huống như vậy là khi bạn làm việc với các gói, thư viện, mô-đun hoặc API của bên thứ ba.

Trong những tình huống như thế này, bạn có thể không phải lúc nào cũng biết điều gì sẽ xảy ra. Điều này đặc biệt đúng nếu gói, mô-đun hoặc thư viện bạn đang làm việc không có định nghĩa loại. Trong trường hợp đó, việc sử dụng bất kỳ sẽ cho phép mã của bạn biên dịch mà không cần phải mất hàng giờ cố gắng tìm ra tất cả các loại cần thiết.

Một tình huống khác có thể được sử dụng là khi bạn muốn viết lại mã JavaScript của mình thành TypeScript. Trong trường hợp ứng dụng React, khi bạn muốn chuyển sang React và TypeScript. Việc sử dụng bất kỳ sẽ ngăn chặn nhiều lỗi mà bạn sẽ phải đối phó. Với bất kỳ, bạn có thể giải quyết từng cái một mà không làm hỏng ứng dụng của mình.

Điều đó nói rằng, tôi vẫn thà tắt quy tắc nghiêm ngặt, trong trường hợp này, hãy chú thích mã của bạn đúng cách. Sau đó, bật lại quy tắc nghiêm ngặt. Lý do là sử dụng bất kỳ có thể dẫn đến thói quen và thực hành xấu. Như có câu nói, "làm một lần, làm hai lần và nó trở thành thói quen". Một khi bạn bắt đầu sử dụng bất kỳ, có thể khó dừng lại với nó.

Don’t be afraid of using interfaces (or type aliases)

Một số nhà phát triển JavaScript và React không thích ý tưởng sử dụng giao diện hoặc nhập bí danh. Họ thấy nhiều mã hơn trong trình soạn thảo của họ và họ tự động cho rằng mã đã biên dịch cũng sẽ trở nên lớn hơn. Nó sẽ lộn xộn bởi mã được tạo cho các giao diện. Điều này sẽ không xảy ra.

Khi bạn tạo và sử dụng một giao diện trong mã của mình, TypeScript sẽ chỉ sử dụng mã đó để thực hiện việc kiểm tra kiểu trong thời gian chạy và biên dịch. Tuy nhiên, nó sẽ không biên dịch mã đó. Không một dòng mã nào của bạn cho các giao diện sẽ kết thúc bằng JavaScript đã biên dịch. Hãy xem một ví dụ đơn giản.

Hãy tạo một giao diện với bốn thuộc tính, tên (chuỗi), tuổi (số), nghề nghiệp (chuỗi) và yearOfBirth (số). Tiếp theo, hãy khai báo một biến mới, một đối tượng, được gọi là stan và khởi tạo nó với một số dữ liệu, sử dụng giao diện để xác định hình dạng của biến này. Khi bạn biên dịch mã này, chỉ stan biến sẽ còn lại.

// This:
interface UserInterface {
    name: string;
    age: number;
    occupation: string;
    yearOfBirth: number;
}

const stan: UserInterface = {
    name: 'Stan Drake',
    age: 29,
    occupation: 'programmer',
    yearOfBirth: 1990
}

// Will compile to this:
"use strict";
const stan = {
    name: 'Stan Drake',
    age: 29,
    occupation: 'programmer',
    yearOfBirth: 1990
};

The same is also true for type aliases. They will also not be compiled.

// This:
type Book = {
    title: string,
    author: string,
    numberOfPages: number,
    publicationDate: number,
}

const warAndPeace: Book = {
    title: 'War and Peace',
    author: 'Leo Tolstoy',
    numberOfPages: 1296,
    publicationDate: 1869,
}

// Will compile to this:
"use strict";
const warAndPeace = {
    title: 'War and Peace',
    author: 'Leo Tolstoy',
    numberOfPages: 1296,
    publicationDate: 1869,
};

Như bạn có thể thấy, giao diện và bí danh loại không dẫn đến sự lộn xộn trong biên dịch mã. Chúng sẽ không làm cho mã đã biên dịch của bạn lớn hơn. Mã đã biên dịch của bạn sẽ giữ nguyên bất kể bạn sử dụng bao nhiêu giao diện và kiểu bí danh. Vì vậy, đừng lo lắng về điều này và tiếp tục sử dụng các giao diện và nhập bí danh để chú thích mã của bạn.

Interfaces, type aliases… Don’t over-think, just be consistent

Không sớm thì muộn, khi bạn bắt đầu với React và TypeScript, hoặc chỉ TypeScript, bạn sẽ nghe thấy cuộc thảo luận về giao diện và bí danh kiểu. Có một số nhà phát triển thích sử dụng giao diện. Những người khác thích sử dụng bí danh loại. Cả hai nhóm này đều có lý do của họ để làm như vậy.

Tôi đề nghị bạn nên bỏ qua những điều đó, ít nhất là trong thời gian đầu. Có nhiều điều quan trọng để học, thực hành hoặc tranh luận hơn là giao diện và bí danh loại. Điều này giống như có một cuộc thảo luận về dấu chấm phẩy và không có dấu chấm phẩy. Những cuộc thảo luận này không quá quan trọng đối với việc học cách sử dụng JavaScript hoặc TypeScript.

Có, có một số khác biệt giữa giao diện và bí danh kiểu. Cả hai đều có ưu và nhược điểm của họ. Tuy nhiên, cả hai đều sẽ giúp bạn hoàn thành công việc. Vì vậy, đừng nghĩ quá nhiều. Đọc về giao diện, loại bí danh và sự khác biệt của chúng, thử cả hai và xem bạn thích cái nào hơn. Sau đó, hãy kiên trì lựa chọn đó.

Ví dụ, tôi thích sử dụng các giao diện. Tôi cảm thấy thoải mái khi làm việc với họ và họ làm cho mã dễ đọc hơn đối với tôi. Bạn có thể không thích điều này. Bạn có thể thích loại bí danh. Vậy thì, hãy là khách của tôi. Một cách tiếp cận khác là sử dụng cả hai. Một số người thích sử dụng giao diện để xác định API cho thư viện và định nghĩa loại của bên thứ ba.

Sau đó, họ sử dụng bí danh loại cho các thành phần và đạo cụ React. Những người khác sử dụng giao diện cho các thành phần và đạo cụ React và chỉ nhập bí danh cho các biến và hàm. Hãy thử tất cả các cách tiếp cận, tìm hiểu về ưu và nhược điểm và đưa ra quyết định của bạn. Cuối cùng, đây là điều quan trọng. Gắn bó với một thứ và không liên tục chuyển đổi.

Nếu bạn quyết định chỉ sử dụng các giao diện, hãy làm điều đó và chỉ sử dụng chúng. Nếu gõ bí danh, điều tương tự. Nếu bạn quyết định sử dụng cả hai, hãy tiếp tục từng trường hợp trong các trường hợp đặc biệt. Giao diện hoặc gõ bí danh… Hãy nhớ rằng, đó là mã của bạn. Viết nó theo cách bạn thích, giả sử bạn tuân theo các thông lệ tốt và kết quả sẽ không phải là một đống lộn xộn.

Don’t annotate everything, embrace automatic type inference

Các nhà phát triển bắt đầu với TypeScript đôi khi nghĩ rằng cần phải chú thích tất cả mã của họ. Tôi cũng nghĩ như vậy. Đây không phải là sự thật. Khi bạn bắt đầu sử dụng TypeScript, điều đó không có nghĩa là bạn phải chú thích từng dòng mã của mình. Điều đó không có nghĩa là bạn phải suy ra loại của mọi biến, hàm, v.v.

Đây là một điều tốt đẹp trên TypeScript. Nó sẽ làm rất nhiều việc cho bạn. Một phần của công việc này là tự động suy ra các loại, trong các tình huống cụ thể. Đây là điều mà chúng ta đã thảo luận trong phần thứ hai. Tóm tắt nhanh. TypeScript sẽ suy ra (và mong đợi) kiểu cho bạn nếu bạn khai báo và cũng khởi tạo một biến.

Khi bạn thực hiện việc này, TypeScript sẽ tự động sử dụng kiểu giá trị mà bạn đã gán cho biến đó để suy ra giá trị của nó. Ví dụ: nếu bạn khởi tạo một số biến với số, bạn gán một số cho nó, TypeScript sẽ tự động suy ra (và mong đợi) loại số. Tương tự với chuỗi, boolean hoặc bất kỳ kiểu nào khác.

Một tình huống khác khi TypeScript sẽ tự động suy ra loại cho bạn là nếu bạn đặt (các) giá trị mặc định cho (các) tham số hàm. Trong trường hợp đó, TypeScript sẽ sử dụng giá trị mặc định để suy ra kiểu. Vì vậy, nếu một số tham số có giá trị mặc định là một chuỗi, TypeScript sẽ suy ra (và mong đợi) loại chuỗi.

Tình huống thứ ba là khi hàm trả về một số giá trị. Trong trường hợp đó, bạn không phải tự mình suy ra loại trả lại. Chà, nếu nó không trả về bất kỳ thứ gì, TypeScript sẽ suy ra loại void. Vì vậy, nó hoạt động tốt. Nếu bạn nhớ ba trường hợp này, chắc chắn bạn sẽ không lãng phí thời gian để ghi chú mã không cần chú thích.

///
// No.1: Declaring and initializing variables
// Note: let and const doesn't make a difference
const name = 'Jackie'
// TypeScript will automatically infer type of 'string'

let year = 2020
// TypeScript will automatically infer type of 'number'

const isReady = true
// TypeScript will automatically infer type of 'boolean'

let subjects = ['Math', 'History', 'English']
// TypeScript will automatically infer type of 'string[]'


///
// No.2: Function with parameter(s) with default value(s)
function defaultParam(age = 18) {
  // ...
}
// TypeScript will automatically infer function defaultParam(age?: number): void
// Function not returning anything with a parameter type of number

const defaultParam = (name = 'anonymous') => {
  // ...
}
// TypeScript will automatically infer const defaultParam: (name?: string) => void
// Function not returning anything with a parameter type of string


///
// No.3: Function returning something
function returnAString() {
  return 'This is gonna be heavy!'
}
// TypeScript will automatically infer function returnAString(): string
// Function with a return type of string

const returnANumber = () => {
  return 2**15
}
// TypeScript will automatically infer const returnANumber: () => number
// Function with a return type of number

Last updated

Was this helpful?