不定期更新,建議關注收藏點贊。
目錄
- 簡介
- 使用
- 基本類型、類型推斷和類型注解
- 接口、類型別名、聯合類型
- 類與繼承
- 泛型Generics
- React 與 TS
- 進階
- 高級類型
- 裝飾器Decorators
- 模塊系統
- TypeScript 編譯選項
簡介
TypeScript(簡稱 TS)是一種由微軟開發的開源編程語言,是 JavaScript 的超集。在 JavaScript 的基礎上增加了靜態類型檢查等其他功能,使得開發者可以在編寫代碼時更早地發現潛在的錯誤,從而提高代碼的質量和可維護性。
“超集”是指一種包含原始語言或集合的語言或集合。
比如:如果 A 是 B 的超集,那意味著 A 包含了 B 的所有元素或特性,同時可能還額外包含一些元素或特性。
在 TypeScript 和 JavaScript 的關系中,TypeScript 是 JavaScript 的超集,表現為:
所有合法的 JavaScript 代碼 都是有效的 TypeScript 代碼,甚至可以直接運行。
TypeScript 在 JavaScript 的基礎上添加了類型系統和其他一些功能(如類、接口等),因此 TypeScript 擴展了 JavaScript,提供了更多的特性,但依然保留了 JavaScript 的所有內容。
- 作用:使JS更嚴謹可靠,提高質量和可維護性
- 主要特點
靜態類型:TypeScript 允許你在編寫代碼時指定變量、函數參數、返回值等的類型。這樣可以在編譯階段檢查類型錯誤,避免了 JavaScript 動態類型的潛在問題。
編譯為 JavaScript:TypeScript 本身不能直接在瀏覽器中運行,必須先編譯成 JavaScript 代碼,而編譯后的代碼可以在所有支持 JavaScript 的環境中運行。
面向對象編程支持:TypeScript 提供了類、接口、繼承等面向對象編程的特性,讓代碼更加結構化。
開發工具支持:TypeScript 提供了更強大的編輯器支持,比如自動完成、代碼提示、跳轉到定義等功能,可以提高開發效率。
使用
基本類型、類型推斷和類型注解
- 基本類型
TypeScript 的一大優勢就是靜態類型檢查。最基礎的是理解 TypeScript 的基本類型和如何使用它們。
基本類型:
number:用于表示數字類型。
string:用于表示字符串類型。
boolean:用于表示布爾值類型。
null 和 undefined:表示空值和未定義的變量。
any:任何類型,禁用類型檢查,應該盡量避免使用。
void:通常用于表示函數沒有返回值。 - 類型推斷:TypeScript 會根據變量的初始值來自動推斷變量的類型。
let name = "John"; // 推斷為 string
let age = 30; // 推斷為 number
- 類型注解
TypeScript 允許你顯式指定變量、函數參數和返回值的類型,幫助提前發現錯誤。
//變量類型注解
let name: string = "Alice";
let age: number = 25;function greet(name: string): string {//函數類型注解return "Hello, " + name;
}
TypeScript 中的數組和元組支持類型注解。
元組是一種特殊的數組,允許存儲不同類型的值,且長度固定。(注意區別python元組)
let numbers: number[] = [1, 2, 3];let tuple: [string, number] = ["Alice", 30];
接口、類型別名、聯合類型
- 接口用于定義對象的結構,TypeScript 強烈推薦使用接口來描述對象類型。
//對象類型接口
interface Person {name: string;age: number;
}const person: Person = {name: "Alice",age: 30,
};//可選屬性和只讀屬性
interface Person {name: string;age?: number; // 可選屬性readonly id: string; // 只讀屬性
}
- 類型別名 (Type Aliases)
類型別名可以為類型提供一個新的名字,可以用于簡化復雜類型或給已有類型起個更直觀的名字。
type ID = string | number;function printId(id: ID): void {console.log(id);
}
- 聯合類型 (Union Types)
Union 類型允許一個變量或參數可以是多種類型之一。你可以使用 | 符號來定義聯合類型。
function printId(id: string | number): void {console.log(id);
}printId(123); // 合法
printId("abc"); // 合法
類與繼承
TypeScript 提供了對面向對象編程(OOP,Object Oriented Programming)的良好支持,特別是類和繼承。
//類和構造函數
class Person {name: string;age: number;constructor(name: string, age: number) {this.name = name;this.age = age;}greet(): string {return `Hello, I'm ${this.name}.`;}
}const person = new Person("Alice", 30);//繼承
class Employee extends Person {role: string;constructor(name: string, age: number, role: string) {super(name, age);this.role = role;}describe(): string {return `${this.name} is a ${this.role}`;}
}const employee = new Employee("Bob", 25, "Developer");
泛型Generics
泛型,就是我不確定具體類型,先占個位,等用的時候再指定。
- 作用:泛型允許你定義能夠處理多種類型的函數、接口和類,增強代碼的復用性和類型安全。
function identity<T>(arg: T): T {return arg;
}
<T>
:占位符,表示"某種類型",但暫時不知道是什么。
arg: T
:這個參數是 T 類型。
: T
:函數返回值也是 T 類型。
//函數
function identity<T>(arg: T): T {return arg;
}let result = identity<string>("Hello");//接口
interface Box<T> {value: T;
}
const box: Box<number> = { value: 123 };
React 與 TS
在 React 項目中,使用 TypeScript 能讓你在處理狀態、props、組件等方面更加得心應手,避免了類型錯誤。
項目 | 老寫法(React 16-17) | 新寫法(React 18+) |
---|---|---|
import React | 必須寫 | 不用寫了 |
用 React.FC | 常用 | 不推薦,用 Props 明確寫 |
useState/useEffect | 基本一致 | 基本一致 |
- 不強制 import React 了
因為從 React 17 新的 JSX 轉換開始,編譯器自己知道怎么處理 JSX,不需要手動 import。
//沒有 import React from 'react',也不用 React.FC
interface Props {name: string;
}
//({ name }: Props)這個{name}是否解構props
//解構的話直接拿到 name,不需要 props.name,更方便。
const MyComponent = ({ name }: Props) => {return <h1>Hello, {name}!</h1>;
}
//未解構
const MyComponent = (props: Props) => {return <h1>Hello, {props.name}!</h1>;
}
- 很多人現在不推薦用 React.FC 來定義組件了
原因:React.FC 會自動加上 children 屬性,可能讓類型不準確。寫法麻煩。 - 沒變化:useState 和 useEffect 的類型
- useEffect 基本不用專門加類型,除非你需要在里面用復雜的異步處理。
- useEffect 跟 useState 是完全不一樣的設計
useState —— 是泛型函數,因為它需要知道你存的數據類型是什么。
useEffect —— 是普通函數,根本不需要泛型,因為它就是執行副作用(side effect),不是操作數據!
const [count, setCount] = useState<number>(0);
//useState<T>(initialValue) 給初始值加類型是非常標準的用法。
/*
返回值這里沒有指定類型是因為
TypeScript 已經根據 useState<number>() 的返回類型,自動推導出來了
指定一次,后面全自動繼承。
*/
function useState<T>(initialValue: T): [T, (newValue: T) => void] {let value = initialValue;function setValue(newValue: T) {value = newValue;console.log("新值:", value);}return [value, setValue];
}useEffect(() => {console.log("Component mounted");
}, []);
進階
高級類型
(例如映射類型、條件類型等),這些通常出現在一些高難度的面試題和庫的開發中。
裝飾器Decorators
模塊系統
在 TypeScript 中,模塊和命名空間用于組織代碼。模塊通過 export 和 import 來進行模塊化管理。
// file1.ts
export function greet(name: string) {return `Hello, ${name}!`;
}// file2.ts
import { greet } from './file1';console.log(greet("Alice"));
- 命名空間(Namespace)
用來組織代碼的工具,給代碼加一個盒子,防止名字沖突。
比如:兩個函數,名字都叫 sum,那肯定打架!放到不同的命名空間里面,就互不干擾了。
命名空間是 老時代 TypeScript 管理代碼的方法。現在更推薦用 模塊(import/export)來組織代碼。
namespace MathTools {
//加了 export,外面才能訪問里面的函數,不然是私有的。export function sum(a: number, b: number): number {return a + b;}export function multiply(a: number, b: number): number {return a * b;}
}let result1 = MathTools.sum(1, 2); // 3
let result2 = MathTools.multiply(3, 4); // 12
TypeScript 編譯選項
深入理解 TypeScript 的編譯器選項,優化項目的構建過程,特別是在大型應用中。