Có nên sử dụng Typescript để phát triển ứng dụng React?

Mở bài

TypeScript là ngôn ngữ mã nguồn mở miễn phí được phát triển và bảo trì bởi Microsoft.
Nó là tập cha của JavaScript, với các bổ sung về kiểu dữ liệu (string, number, boolean, undefined, null, …) và lớp hướng đối tượng, điều mà ở JavaScript còn thiếu sót.

Thân bài

1) Cú pháp, sử dụng

Về cơ bản, khi đóng gói ứng dụng TypeScript sẽ được IDE compile thành JavaScript. Nên các ứng dụng viết bằng JavaScript đều có thể viết bằng TypeScript.

Một số ví dụ khi sử dụng TypeScript:

const isDone: boolean = true;
const height: number = 8;
const list: string[] = ["yasuo", "master yi"];
const add = (x: number, y: number): number => {
    return x+y;
}

Và một số tính năng bổ sung mà JavaScript không có:

enum Department {
    'MageX',
    'Coffee',
    'Sales',
    'Shark',
    'WHO',
    'Noodle',
    'Empty',
}
const myTeam = Department.Shark

// or

type Department = "MageX" | "Coffee" | "Sales" | "Shark" | "WHO" | "Noodle" | "Empty"
const myTeam: Department = "Shark"

// or

interface Employer {
    name: string
    birth: string | null
    department: Department
}

const eren: Employer = {
    name: "Eren Pham",
    birth: "2004",
    department: "Shark"
}

=> Tham khảo thêm nhiều cú pháp tại: https://www.typescriptlang.org/

2) Sử dụng Typescript mang lại lợi ích gì?

  • Hỗ trợ OOP mạnh: Hầu hết các cú pháp hướng đối tượng đều được hỗ trợ bởi Typescript như kế thừa, đóng gói, constructor, abstract, interface, implement, override…v.v
  • Code dễ đọc, tường minh hơn, cú pháp và kiểu dữ liệu rõ ràng.
  • Ít lỗi, dễ bảo trì: Không giống như JavaScript, trong quá trình code TypeScript, lỗi thường được thông báo ngay trong quá trình biên dịch
// The given type is boolean, the provided value is a string.
var tasty: boolean = "I haven't tried it yet";

main.ts(1,5): error TS2322: Type ‘string’ is not assignable to type ‘boolean’.

3) Vậy nhược điểm của Typescript?

- Vẫn còn mạo hiểm để sử dụng

Một ứng dụng viết bằng Typescript (.ts, .tsx) không thể sử dụng song song với JavaScript (.js, .jsx) vì đoạn mã JavaScript thiếu đi “types” của Typescript. Trừ khi được định nghĩa “types” riêng bới file “.d.ts” (.*.ts = *.js + *.d.ts). Do còn mới nên các thư viện chưa hỗ trợ Typescript sẽ không sử dụng được trong ứng dụng Typescript, nếu muốn sử dụng bạn phải viết tập tin “.d.ts” declare cho toàn bộ function liên quan trong đó :scream: Nhưng đó là câu chuyện của 1,2 năm trước. Còn ở thời điểm hiện tại, năm 2020 rồi thì phần lớn thư viện đều support TypeScript nên hãy yên tâm nhé :wink:
Dấu hiệu nhận diện 1 thư viện hỗ trợ typescript là trong thư mục gốc có chứa tập tin “.d.ts”:
Screen Shot 2020-08-01 at 17.54.34
Hoặc sẽ có 1 thư viện có tên “@types/[packge]” do cộng đồng đóng góp khi tác giả chưa hỗ trợ TypeScript

- Đôi khi quá cồng kềnh

Nhược điểm này cũng đến chính từ ưu điểm mà nó mang lại, việc khai báo kiểu dữ liệu đôi khi khiến code trở nên cồng kềnh, mất thời gian. Ví dụ thay vì code JavaScript như thế này

static create = (subscribe) => {
  return new Observable(subscribe);
}

thì code TypeScript lại như thế này

static create: Function = <T>(subscribe?: (subscriber: Subscriber<T>) => TeardownLogic): Observable  => {
  return new Observable<T>(subscribe);
}

hoặc như thế này :flushed:

;((currentReducer as unknown) as Reducer<NewState,NewActions>) = nextReducer

4) React & TypeScript

Hiện React (bao gồm cả ReactJS vs ReactNative) đều hỗ trợ sẵn TypeScript, không còn cài đặt webpack phức tạp như trước.
Để khởi tạo ứng dụng ReactJS sư dụng TypeScript dùng lệnh:

npx create-react-app my-app --template typescript
# or
yarn create react-app my-app --template typescript

Các tập tin đuôi “.js” sẽ được đổi thành “.ts”.
Các tập tin chứa component của React sẽ là “.tsx”

Kết bài

Việc sử dụng TypeScript để phát triển ứng dụng hay không phụ thuộc vào nhiều yếu tố như phạm vi của dự án, sở thích của các thành viên trong team (sẽ có người thích người không). Nhưng để phát triển một dự án lớn, chuyên nghiệp, cần sự ổn định thì câu trả lời là NÊN :wink:

2 Likes

Em có thể lập bảng đối chiếu so sánh các yếu tố giữa TypeScript và JavaScript không, hoặc dẫn các nguồn đánh giá so sánh giữa 2 cái.

Những gì TypeScript bổ sung thêm vào JavaScript em đã example trong phần cú pháp rồi anh, ngoài types và interface thì TypeScript kế thừa toàn bộ cú pháp của JavaScript ạ

1 bài viết nói khá chi tiết về ưu điểm TypeScript

JS cũng có OOP tại sao phải dùng thêm OOP của ts nữa a

Đúng ra OOP của JS thuần hơi siđa, cũng ko biết có được gọi là OOP không nữa
chứ class JS thuần trông sẽ như thế này

var employee = {
    name: null,
    age: null,
    setName: function (name) {
        this.name = name;
    },
    getName: function () {
        return this.name;
    },
    setAge: function (age) {
        this.age = age;
    },
    getAge: function () {
        return this.age;
    }
};

còn cái JS mà React đang dùng là 1 biến thể nâng cấp của JS gọi là ES6 hay ES2015 hay ECMAScript 2015

class Employee {
    setName (name) {
        this.name = name;
    }
    getName () {
        return this.name;
    }
    setAge (age) {
        this.age = age;
    }
    getAge () {
        return this.age;
    }
};

Tuy nhiên JS của React không hỗ trợ Interface


hay abstract class
image
Nên a nghĩ TS sinh ra để bù đắp phần này :smiley: đoạn nói về OOP trên chắc chưa đúng lắm, để a sửa lại.

À, nghĩ lại thì vẫn có ý đúng, vì đoạn giới thiệu về TS là đang so sánh TS với JS thuần chứ ko phải ES6, nên đoạn bổ sung OOP là đúng :grin:

Khi chuyển sang dùng TypeScript thì sẽ trông như thế nào

Khi chưa dùng TypeScript

import React from 'react'
import PropTypes from 'prop-types'

class Greeting extends React.Component {
    constructor(props) {
        super(props)
        this.state = {
            date: new Date(),
        }
    }
    render() {
        return <h1>Hello, {this.props.name}</h1>
    }
}

Greeting.propTypes = {
    name: PropTypes.string.isRequired,
    message: PropTypes.string,
}

Khi chuyển sang TypeScript

import React from 'react'

interface GreetingProps {
    name: string
    message?: string
}

interface GreetingState {
    date: Date
}

class Greeting extends React.Component<GreetingProps, GreetingState> {
    state: GreetingState = {
        date: new Date()
    };

    render() {
        return (
            <h1>Hello, {this.props.name}</h1>
        );
    }
}

Hoặc (TypeScript + Hook): best choice ở thời điểm hiện tại :partying_face:

import React, { useState } from 'react'

interface GreetingProps {
    name: string
    message?: string
}

const Greeting = (props: GreetingProps) => {
    const [date, setDate] = useState<Date>(new Date())
    return <h1>Hello, {props.name}</h1>
}