[TS] TypeScript Getting Started
此篇為各筆記之整理,非原創內容,資料來源可見下方連結與文後參考資料。
CLI
$ npm init -y # 初始化 npm
$ npm install -D typescript # 安裝 typescript
$ npx tsc --init # 產生 TS 設定檔 tsconfig.json
$ npx ts-node index.ts
# 將 TS 編譯成 JS
$ tsc # Run a compile based on a backwards look through the fs for a tsconfig.json
$ tsc index.ts
$ tsc src/*.ts # Transpile any .ts files in the folder src, with the default settings
$ tsc --watch # 常駐使用語法檢測
- ts-node-dev:當檔案有變更時能夠自動重啟(不是自動重新打包)
- ts-node:不需重新打包就可以直接執行 ts 檔
For Development
透過 nodemon 搭配 ts-node 自動 reload 與編譯
How to watch and reload ts-node when TypeScript files change @ stackOverflow
在根目錄建立 nodemon.json
,並撰寫以下設定:
// nodemon.json
{
"watch": ["src"],
"ext": "ts,json",
"ignore": ["src/**/*.spec.ts"],
"exec": "npx ts-node ./src/index.ts"
}
使用 ts-node 的注意事項
使用 ts-node
時需要留意在 tsconfig.json
中的 module
是否有設定為 "module": "commonjs"
,否則會出 現錯誤訊息:
Warning: To load an ES module, set "type": "module" in the package.json or use the .mjs extension.
但如果根據它的建議修改,會出現另一個錯誤:
TypeError [ERR_UNKNOWN_FILE_EXTENSION]: Unknown file extension ".ts" for
正確的解決方式只需要把 tsconfig.json
中的 module
設為 commonjs
即可(參考:ts-node execute typescript with module import and module defined)。
概念
- 為某變數定義型別的方式稱作「型別註記(type annotations)」,又稱作 type declarations,例如,
let firstName: string
。 - 當我們宣告變數而沒有使用型別註記時,TypeScript 會自動進行「型別推論(type inference)」的動作,也就是幫每個變數進行預設的型別註記。
- 有時你會明確知道某變數的型別,但 TypeScript 並不知道這些資訊,這時候可以使用「型別斷言(type assertion)」
Type
readonly properties
keywords: Readonly
type Todo = {
readonly id: number;
readonly text: string;
readonly done: boolean;
};
// 等同於
type Todo = Readonly<{
id: number;
text: string;
done: boolean;
}>;
// 讓陣列不能被改變 readonly Array of Todo
type Todos = readonly Todo[];
literal types (exact value)
type CompletedTodo = Readonly<{
id: number;
text: string;
done: true; // 在定義 type 的時候,直接定義要使用某個值
}>;
Intersection and Union types
keywords: &
, |
intersection type
type A = { a: number };
type B = { b: string };
// This intersection type…
type AAndB = A & B;
// 等同於
type AAndB = {
a: number;
b: string;
};
如果兩個屬性名稱相同,比較嚴格的規則(true
)會把較不嚴格的規則(boolean
)覆蓋(取交集的概念);但若兩個規則互斥無法取得交集時,則會變成 never
:
// B 的規則比 A 更嚴格
type A = { foo: boolean };
type B = { foo: true };
// 取得交集之後
type AAndB = A & B;
// 等同於
type AAndB = { foo: true };
透過這種方式,我們可以用原有的型別定義新的型別:
type Todo = Readonly<{
id: number;
text: string;
done: boolean;
}>;
// Override the done property of Todo
type CompletedTodo = Todo & {
readonly done: true;
};
Union Type
// 建立一個 Foo type,它是 number 和 string 的交集
type Foo = number | string;
// 使用 Foo 型別時,可以同時是 number 或 string
const a: Foo = 1;
const b: Foo = 'hello';
也可以搭配 literal type
:
type Place = 'home' | 'work' | { custom: string };