前言
最近用 TypeScript 寫 npm 包,各種模塊、命名空間、全域定義等等擾得我睡不著覺,
我便苦心研究,總結了幾個比較冷門的,國內貌似基本上找不到資料的匯入匯出用法,順便在其中又插入一些不那么冷門的用法,于是本篇文章來了,
因為一開始也沒想做成大全,可能之后還會繼續更新吧,
目錄
- 匯入模塊
- 在模塊中匯出
- 匯入命名空間
- 在命名空間中匯出
- 使用全域定義
- 進行全域定義
匯入模塊
匯入模塊中的東西相信大家都不陌生,唯一需要注意的便是默認匯出與“星號”匯出的區別,
import * as Mod from './mod';
// 類似于
const Mod = require('./mod');
import ModDef from './mod';
// 類似于
const { default: ModDef } = require('./mod');
import ModDef, { a, b } from './mod';
// 類似于
const {
default: ModDef,
a, b
} = require('./mod');
在模塊中匯出
在模塊中匯出東西相信大家也不陌生,不過這里還是詳細講解一下,
在模塊中匯出東西有很多種方法,匯出總共可分為 4 類:
- 命名匯出
- 默認匯出
- 星號匯出
- 匯出分配
命名匯出
命名匯出有兩種方法,一種是宣告著匯出
export namespace A { }
export function b() { }
export class C { }
export const d = 123;
export let { e } = { e: 'hh' };
一種是宣告后匯出
namespace A { }
function b() { }
class C { }
const d = 123;
let { e } = { e: 'hh' };
export { A, b, C, d, e };
宣告后匯出比宣告著匯出更靈活,能合并,也能重命名
namespace A { }
export { A };
function b() { }
export { b as c };
class C { }
export { C as B };
const d = 123;
let { e } = { e: 'hh' };
export { d, e };
命名匯出編譯成 Common JS 后類似這樣
exports.xxx = xxx;
需要注意的是其他人無法修改任何你匯出的東西,即使是使用 let 宣告也一樣
/* mod.ts */
export let a = 123;
/* others.ts */
import { a } from './mod';
a = 321; // 報錯:ts(2632)
不過對于上面的代碼,你可以隨便修改所匯出的 a ,因為其他人每次讀取 a 時都會重新從你的匯出物件上訪問一次 a 屬性,不用擔心其他人無法接收到你的修改,具體可以查看編譯后的 JS 檔案
/* others.ts */
import { a } from './mod';
const b = a + 123;
console.log(a);
/* others.js */
var mod_1 = require("./mod");
var b = mod_1.a + 123;
console.log(mod_1.a);
默認匯出
默認匯出可以理解為一種特殊的命名匯出,
默認匯出的名字是 default ,但是你不能搞個名字叫 default 的變數然后匯出,你必須得用 export default 或者在匯出時重命名
export let default = 123; // 報錯:ts(1389)
export default 123; // 正確
export let a = 123;
export { a as default }; // 正確
星號匯入搭配默認匯出,可以達到默認匯出即為星號匯出的效果
/* mod.ts */
import * as Self from './mod';
export default Self;
/* others.ts */
import * as Mod from './mod';
import ModDef from './mod';
console.log(Mod === ModDef); // true
星號匯出
星號匯出可以匯出其他模塊里的東西,一般有兩種用法,
第一種是全匯出到自己里頭,就像
export * from './xxx'
具體效果是 xxx 中匯出的東西,也可以通過你訪問到,
/* xxx.ts */
export let a = { hh: 'hh' };
/* mod.ts */
export * from './xxx.ts';
/* others.ts */
import { a } from './xxx';
import { a } from './mod';
console.log(a === a); // true
第二種是掛到自己模塊下面,就像
export * as xxx from './xxx';
// 等價于
import * as xxx from './xxx';
export { xxx };
匯出分配
匯出分配就是把 Common JS 的匯出搬到了 TS 中,寫法也差不多
export = 'hh';
// 相當于
module.export = 'hh';
匯出分配也可以指定默認匯出,只需要有 default 屬性就可以
/* mod.ts */
export = { default: 123 };
/* others.ts */
import mod from './mod';
console.log(mod); // 123
需要注意的是采用了匯出分配后便不能再使用其他匯出方法,
匯入命名空間
雖然現在命名空間相較于模塊并不是特別常用,但它還是有比較完整的匯入匯出功能的,
匯入命名空間中的東西很簡單,像這樣
import xxx = Space.xxx;
不論你是在模塊中匯入全域命名空間,還是在命名空間中匯入其他命名空間,都是適用的,
import Err = globalThis.Error;
throw Err('hh');
namespace A {
import Process = NodeJS.Process;
let proce: Process;
}
較為可惜的是命名空間貌似沒有星號匯入,也不支持解構匯入,
在命名空間中匯出
在一般 TS 中,命名空間只有兩種方法匯出,
第一種方法是宣告著匯出,類似于模塊
namespace A {
export const a = 123;
}
第二種方法是匯入著匯出,可以用來匯出其他命名空間的東西
namespace A {
export import Err = globalThis.Error;
}
而對于不一般的 TS ——也就是型別宣告中,命名空間還可以采用像模塊一樣的匯出物件
declare namespace A {
const a = 123;
const b = 'hh';
export { a, b };
}
使用全域定義
全域定義一般有三種:
-
內置在 TS 中的全域定義,比如
setTimeout、Error等,
對于這種全域定義,直接拿來用就可以了, -
位于環境模塊中的全域定義,比如
NodeJS.Process等,包括位于
node_modules/@types檔案夾中的自動引入的環境模塊,都可以通過三斜杠注釋來引入,你可以通過
path直接指定檔案路徑/// <reference path="./types.d.ts" /> -
位于模塊中的全域定義,
這種全域定義只需要引入一下模塊,表示你已經運行此模塊,即可
import '@babel/core';或者你也可以通過三斜杠注釋,通過
types指定模塊/// <reference types="@babel/core" />需要注意的是,不論你采用
import還是三斜杠注釋,甚至只是在型別中使用了一個typeof import('xxx'),只要你在一個 TS 檔案中引入了這個模塊所定義的全域型別,那這個型別就會永遠存在下去,污染你的globalThis,
唯一在不污染全域域的情況下運行模塊的方法是使用import()函式動態引入,但這樣子你也拿不到你需要的型別,
進行全域定義
進行全域定義一般有三種方法,
第一種是直接寫環境模塊,不帶任何 import 和 export 一般就會讓編譯器把這當成一個環境模塊,所以,如果你需要防止一個 TS 檔案變成環境模塊導致型別泄露的話,你可以加一個安全無公害的 export { }; ,
第二種是在模塊中定義,只需要把型別定義寫到 declare global 里頭就行
declare global {
const a = 123;
let b: {};
}
a; // 123
b; // {}
第三種是通過合并 globalThis 命名空間來定義,好處是可以使用命名空間的“匯入著匯出”方法,將模塊或者其他命名空間的區域變數變成全域變數
import _Mod from './mod';
declare global {
namespace globalThis {
const a = 123;
export import Mod = _Mod;
}
}
a; // 123
Mod; // typeof import('./mod')
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/549457.html
標籤:其他
