<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
在這篇文章中,我們將使用TypeScript和Jest從頭開始構建和釋出一個NPM包。
我們將初始化一個專案,設定TypeScript,用Jest編寫測試,並將其釋出到NPM。
我們的庫稱為digx
。它允許從巢狀物件中根據路徑找出值,類似於lodash
中的get
函數。
比如說:
const source = { my: { nested: [1, 2, 3] } } digx(source, "my.nested[1]") //=> 2
就本文而言,只要它是簡潔的和可測試的,它做什麼並不那麼重要。
讓我們從建立空目錄並初始化它開始。
mkdir digx cd digx npm init --yes
npm init --yes
命令將為你建立package.json
檔案,並填充一些預設值。
讓我們也在同一資料夾中設定一個git
倉庫。
git init echo "node_modules" >> .gitignore echo "dist" >> .gitignore git add . git commit -m "initial"
這裡會用到TypeScript,我們來安裝它。
npm i -D typescript
使用下面的設定建立tsconfig.json
檔案:
{ "files": ["src/index.ts"], "compilerOptions": { "target": "es2015", "module": "es2015", "declaration": true, "outDir": "./dist", "noEmit": false, "strict": true, "noImplicitAny": true, "strictNullChecks": true, "strictFunctionTypes": true, "strictBindCallApply": true, "strictPropertyInitialization": true, "noImplicitThis": true, "alwaysStrict": true, "noUnusedLocals": true, "noUnusedParameters": true, "noImplicitReturns": true, "noFallthroughCasesInSwitch": true, "noUncheckedIndexedAccess": true, "noImplicitOverride": true, "noPropertyAccessFromIndexSignature": true, "esModuleInterop": true, "forceConsistentCasingInFileNames": true, "skipLibCheck": true } }
最重要的設定是這些:
庫的主檔案會位於src
資料夾下,因此需要這麼設定"files": ["src/index.ts"]
。
"target": "es2015"
確保我們的庫支援現代平臺,並且不會攜帶不必要的墊片。
"module": "es2015"
。我們的模組將是一個標準的ES
模組(預設是CommonJS
)。ES
模式在現代瀏覽器下沒有任何問題;甚至Node從13版本開始就支援ES
模式。
"declaration": true
- 因為我們想要自動生成d.ts
宣告檔案。我們的TypeScript使用者將需要這些宣告檔案。
其他大部分選項只是各種可選的TypeScript檢查,我更喜歡開啟這些檢查。
開啟package.json
,更新scripts
的內容:
"scripts": { "build": "tsc" }
現在我們可以用npm run build
來執行構建...這樣會失敗的,因為我們還沒有任何可以構建的程式碼。
我們從另一端開始。
作為一名負責任的開發,我們將從測試開始。我們將使用jest
,因為它簡單且好用。
npm i -D jest @types/jest ts-jest
ts-jest
包是Jest理解TypeScript所需要的。另一個選擇是使用babel
,這將需要更多的設定和額外的模組。我們就保持簡潔,採用ts-jest
。
使用如下命令初始化jest
組態檔:
./node_modules/.bin/jest --init
一路狂按確認鍵就行,預設值就很好。
這會使用一些預設選項建立jest.config.js
檔案,並新增"test": "jest"
指令碼到package.json
中。
開啟jest.config.js
,找到以preset
開始的行,並更新為:
{ // ... preset: "ts-jest", // ... }
最後,建立src
目錄,以及測試檔案src/digx.test.ts
,填入如下程式碼:
import dg from "./index"; test("works with a shallow object", () => { expect(dg({ param: 1 }, "param")).toBe(1); }); test("works with a shallow array", () => { expect(dg([1, 2, 3], "[2]")).toBe(3); }); test("works with a shallow array when shouldThrow is true", () => { expect(dg([1, 2, 3], "[2]", true)).toBe(3); }); test("works with a nested object", () => { const source = { param: [{}, { test: "A" }] }; expect(dg(source, "param[1].test")).toBe("A"); }); test("returns undefined when source is null", () => { expect(dg(null, "param[1].test")).toBeUndefined(); }); test("returns undefined when path is wrong", () => { expect(dg({ param: [] }, "param[1].test")).toBeUndefined(); }); test("throws an exception when path is wrong and shouldThrow is true", () => { expect(() => dg({ param: [] }, "param[1].test", true)).toThrow(); }); test("works tranparently with Sets and Maps", () => { const source = new Map([ ["param", new Set()], ["innerSet", new Set([new Map(), new Map([["innerKey", "value"]])])], ]); expect(dg(source, "innerSet[1].innerKey")).toBe("value"); });
這些單元測試讓我們對正在構建的東西有一個直觀的瞭解。
我們的模組匯出一個單一函數,digx
。它接收任意物件,字串引數path
,以及可選引數shouldThrow
,該引數使得提供的路徑在源物件的巢狀結構中不被允許時,丟擲一個異常。
巢狀結構可以是物件和陣列,也可以是Map和Set。
使用npm t
執行測試,當然,不出意外會失敗。
現在開啟src/index.ts
檔案,並寫入下面內容:
export default dig; /** * A dig function that takes any object with a nested structure and a path, * and returns the value under that path or undefined when no value is found. * * @param {any} source - A nested objects. * @param {string} path - A path string, for example `my[1].test.field` * @param {boolean} [shouldThrow=false] - Optionally throw an exception when nothing found * */ function dig(source: any, path: string, shouldThrow: boolean = false) { if (source === null || source === undefined) { return undefined; } // split path: "param[3].test" => ["param", 3, "test"] const parts = splitPath(path); return parts.reduce((acc, el) => { if (acc === undefined) { if (shouldThrow) { throw new Error(`Could not dig the value using path: ${path}`); } else { return undefined; } } if (isNum(el)) { // array getter [3] const arrIndex = parseInt(el); if (acc instanceof Set) { return Array.from(acc)[arrIndex]; } else { return acc[arrIndex]; } } else { // object getter if (acc instanceof Map) { return acc.get(el); } else { return acc[el]; } } }, source); } const ALL_DIGITS_REGEX = /^d+$/; function isNum(str: string) { return str.match(ALL_DIGITS_REGEX); } const PATH_SPLIT_REGEX = /.|]|[/; function splitPath(str: string) { return ( str .split(PATH_SPLIT_REGEX) // remove empty strings .filter((x) => !!x) ); }
這個實現可以更好,但對我們來說重要的是,現在測試通過了。自己用npm t
試試吧。
現在,如果執行npm run build
,可以看到dist
目錄下會有兩個檔案,index.js
和index.d.ts
。
接下來就來發布吧。
如果你還沒有在npm上註冊,就先註冊。
註冊成功後,通過你的終端用npm login
登入。
我們離釋出我們的新包只有一步之遙。不過,還有幾件事情需要處理。
首先,確保我們的package.json
中擁有正確的後設資料。
main
屬性設定為打包的檔案"main": "dist/index.js"
。"types": "dist/index.d.ts"
。"type": "module"
。name
和description
也應填寫。接著,我們應該處理好我們希望釋出的檔案。我不覺得要釋出任何組態檔,也不覺得要釋出原始檔和測試檔案。
我們可以做的一件事是使用.npmignore
,列出所有我們不想釋出的檔案。我更希望有一個"白名單",所以讓我們使用package.json
中的files
欄位來指定我們想要包含的檔案。
{ // ... "files": ["dist", "LICENSE", "README.md", "package.json"], // ... }
終於,我們已經準備好發包了。
執行以下命令:
npm publish --dry-run
並確保只包括所需的檔案。當一切準備就緒時,就可以執行:
npm publish
讓我們建立一個全新的專案並安裝我們的模組。
npm install --save digx
現在,讓我們寫一個簡單的程式來測試它。
import dg from "digx" console.log(dg({ test: [1, 2, 3] }, "test[0]"))
結果非常棒!
然後執行node index.js
,你會看到螢幕上列印1
。
我們從頭開始建立並行布了一個簡單的npm包。
我們的庫提供了一個ESM模組,TypeScript的型別,使用jest
覆蓋測試用例。
你可能會認為,這其實一點都不難,的確如此。
原文連結:www.strictmode.io/articles/bu…
以上就是詳解如何釋出TypeScript編寫的npm包的詳細內容,更多關於TypeScript npm包釋出的資料請關注it145.com其它相關文章!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45