模組化設計
當一個檔案程式碼愈來愈多,程式的管理會愈來愈困難,為了建構容易維護,能夠擴展的應用程式,模組化是不可或缺的技術,因此現代的程式語言都會提供模組化的支持。Javascript在2015年的ES6引入了標準的模組系統,因此有了統一的模組化支持,Typescript作為Javscript的超集,當然也支持了ES6的模組系統。今天我們將帶大家了解Typescript的模組化概念和實作。
TypeScript主要透過 export
和 import
這兩個關鍵字來實現,任何包含頂層 import
或 export
的檔案都會被視為一個模組,為了保證我們的typescript檔案被視為模組,我們可以先在檔案上加入下列的敘述,即使我們沒有使用這段敘述,如果檔案後來有實際的export
和 import
關鍵字出現,我們再刪除這段敘述。
export {}; // 這個檔案現在被視為模組,並且匯出一個空物件
模組裏的任何變數和函數都有自己的範疇或視野(Scope),除非將它匯出(Export),這些變數或函數在其它檔案是不可見的,可以有效避免全域命名空間的污染。在函數式程式設計中,通常不會有全域變數,因此我們主要匯出的是常數(函數也是一個常數),一個檔案可以匯出超過一個常數,我們將要匯出的常數放入一個物件中,匯出的語法如下:
// @filename: arith.ts
const pi = 3.14159
const add = (x: number, y: number) => x + y
const substract = (x: number, y: number ) => x - y
export {
pi,
add,
substract
}
上面的程式碼也可以用下面的寫法,
// @filename: arith.ts
export const pi = 3.14159
export const add = (x: number, y: number) => x + y
export const substract = (x: number, y: number ) => x - y
這種寫法也是匯出一個物件,這個物件就是{ pi, add, substract},所以兩種寫法可以得到相同的結果。
匯入則是使用關鍵字import
,使用方法如下,匯入的副檔名(.ts)可以省略:
// @filename: index.ts
import { pi, add } from './arith'
console.log(pi) // 3.14159
console.log(add(3, 5)) // 8
將需要常數放入物件中解構即可,如果有不同的模組使用同樣的命名常數,我們可以將用as
關鍵字重新命名。
// @filename: index.ts
import { add as sum } from './arith'
console.log(sum(3, 5)) // 8
如果要要將模組內的所有常數匯入,我們卻不想在匯入時一一寫出所有的常數名,可以用*
代替整個匯出的物件並用as
予以命名,使用各常數再各別存取。
// @filename: index.ts
import * as arith from './arith'
console.log(arith.add(3, 5)) // 8
每個模組最多只能有一個預設匯出, 我們通常用來匯出模組中最主要的那個功能,使用關鍵字default
,
// @filename: arith.ts
const pi = 3.14159
const add = (x: number, y: number) => x + y
const substract = (x: number, y: number ) => x - y
export default add
export {
pi,
substract
}
匯入模組的預設匯出時,可以隨意自行命名並且不需要解構,寫法如下,
// @filename: index.ts
import sum from './arith'
console.log(sum(3, 5)) // 8
我們可以將預設匯出和其它匯出一併寫在一行,再用逗號分開,
/ @filename: index.ts
import sum, { pi, substract } from './arith' // sum is the default export add
console.log(sum(3, 5)) // 8
console.log(pi) // 3.14159
Typescript特有的型別(type)和介面(interface)也可以使用ES6匯出和匯入語法,匯入時我們也可以在型別前面加關鍵字type,以防止匯入的型別被誤用為常數或函數(雖然我們通常會將型別以首字大寫命名作為區別),如此可以讓程式碼更為安全;而且TypeScript 編譯器在編譯成 JavaScript 時完全移除該匯入語句,進行最佳化。,
// @filename: animal.ts
export type Cat = { breed: string; yearOfBirth: number };
export interface Dog {
breeds: string[];
yearOfBirth: number;
}
// @filename: index.ts
import { type Cat, type Dog } from "./animal";
type Animals = Cat | Dog;
我們可以在一個目錄下設置一個index.ts
,當我們匯入的路徑只有目錄名時,typescript會自動匯該index.ts。利用這個特性,我們可以將該目錄下所有模組匯出至index.ts
檔案,然後再統一匯出。
// @pathname: user/types.ts
type User = {
name: string;
age: number;
};
export { User };
// @pathname: user/user.ts
import { type User } from './types';
const getName = (user: User): string => user['name'];
const getAge = (user: User): number => user['age'];
export { getName, getAge };
// @pathname: user/index.ts 這是user子目錄下的index.ts
import { type User } from './types';
import { getName, getAge } from './user';
export { User, getName, getAge };
// @filename: index.ts 這是根目錄下的index.ts
import { User, getName, getAge } from './user';
使用模組化的程式設計可以讓我們更有效率的管理我們的程式,利用目錄匯入的技巧,更能方便的管理我們的模組名稱,可以獨立的增加模組在目錄內而無需更動模組名稱。使用模組匯入的時候,必須注意命名的衝突,適度的更改名稱,讓我們的匯入的函數或常數具備易讀性。今日的分享就到這邊告一段落,明天再見。