基于JS實(shí)現(xiàn)將JSON數(shù)據(jù)轉(zhuǎn)換為T(mén)ypeScript類(lèi)型聲明的工具
在TypeScript 項(xiàng)目中,我們經(jīng)常需要使用聲明一系列的ts類(lèi)型。然而,手動(dòng)寫(xiě)的效率實(shí)在太低,編寫(xiě)一個(gè)自動(dòng)生成ts類(lèi)型的工具可以解放生產(chǎn)力。 實(shí)現(xiàn)一個(gè)工具將 JSON 數(shù)據(jù)轉(zhuǎn)換為 TypeScript 類(lèi)型定義,從而讓 TypeScript 項(xiàng)目更高效的開(kāi)發(fā)。
一、實(shí)現(xiàn)的功能
- 將 JSON 數(shù)據(jù)轉(zhuǎn)換為 TypeScript 類(lèi)型定義。
- 支持嵌套的復(fù)雜類(lèi)型,如數(shù)組和對(duì)象。
- 支持自定義類(lèi)型名稱(chēng)和命名空間。
- 支持將轉(zhuǎn)換后的 TypeScript 類(lèi)型定義保存為文件。
二、工具使用方法
已經(jīng)發(fā)布到npm:my-json-to-ts - npm (npmjs.com)
運(yùn)行效果如下動(dòng)圖:
安裝工具:
npm install -g my-json-to-ts
運(yùn)行工具:
my-json-to-ts input.json output.ts
其中 input.json
是要轉(zhuǎn)換的 JSON 文件路徑,output.ts
是轉(zhuǎn)換后的 TypeScript 文件路徑。
--name 類(lèi)型名稱(chēng) # 指定轉(zhuǎn)換后的類(lèi)型名稱(chēng),默認(rèn)為 JsonType
--namespace 命名空間 # 指定轉(zhuǎn)換后的命名空間,默認(rèn)為無(wú)
--no-file # 不將轉(zhuǎn)換后的 TypeScript 類(lèi)型定義保存為文件
三、實(shí)現(xiàn)思路
- 讀取輸入的 JSON 文件,解析成 JSON 對(duì)象。
- 遍歷 JSON 對(duì)象,根據(jù)不同的類(lèi)型生成對(duì)應(yīng)的 TypeScript 類(lèi)型定義字符串。
- 如果指定了類(lèi)型名稱(chēng)和命名空間,則在生成的 TypeScript 類(lèi)型定義字符串前面添加對(duì)應(yīng)的聲明。
- 如果指定了保存文件,則將生成的 TypeScript 類(lèi)型定義字符串寫(xiě)入文件。
四、使用示例
以下是將JSON 數(shù)據(jù)和轉(zhuǎn)換后的 TypeScript 類(lèi)型定義示例:
簡(jiǎn)單的JSON 數(shù)據(jù)
{ "name": "John", "age": 30, "address": { "city": "New York", "state": "NY" }, "hobbies": [ "reading", "traveling" ] }
輸出對(duì)應(yīng)簡(jiǎn)單的類(lèi)型定義
interface JsonType { name: string; age: number; address: { city: string; state: string; }; hobbies: string[]; }
復(fù)雜的JSON 數(shù)據(jù)
{ "name": "John", "age": 30, "address": { "city": "New York", "state": "NY", "postalCode": 10001 }, "friends": [ { "name": "Jane", "age": 28, "address": { "city": "Los Angeles", "state": "CA" } }, { "name": "Bob", "age": 35, "address": { "city": "Chicago", "state": "IL" } } ], "hobbies": [ "reading", "traveling", { "name": "swimming", "location": "pool" } ] }
輸出對(duì)應(yīng)復(fù)雜類(lèi)型定義
interface JsonType { name: string; age: number; address: { city: string; state: string; postalCode: number; }; friends: { name: string; age: number; address: { city: string; state: string; }; }[]; hobbies: (string | { name: string; location: string; })[]; }
五、具體實(shí)現(xiàn)代碼
首先引入兩個(gè) Node.js 模塊:fs-extra
和 commander
。fs-extra
是一個(gè)簡(jiǎn)化了 Node.js 文件系統(tǒng)模塊的封裝,而 commander
是一個(gè)命令行工具的庫(kù),可以方便地解析命令行參數(shù)。
接下來(lái)定義一個(gè)函數(shù) jsonToTs
,用于將 JSON 數(shù)據(jù)轉(zhuǎn)換為 TypeScript 類(lèi)型定義字符串。該函數(shù)采用遞歸的方式遍歷 JSON 數(shù)據(jù),生成對(duì)應(yīng)的 TypeScript 類(lèi)型定義。如果 JSON 數(shù)據(jù)是數(shù)組,則遞歸處理其中的每個(gè)元素;如果是對(duì)象,則遞歸處理其中的每個(gè)屬性。最終,該函數(shù)返回一個(gè) TypeScript 類(lèi)型定義字符串。
然后定義了兩個(gè)異步函數(shù),readJson
和 writeTs
,分別用于讀取 JSON 文件和將 TypeScript 類(lèi)型定義字符串寫(xiě)入文件。
最后定義一個(gè)名為 jsonToTsFile
的函數(shù),該函數(shù)接收命令行參數(shù)并將其傳遞給 jsonToTs
函數(shù),然后將生成的 TypeScript 類(lèi)型定義字符串保存到文件中。如果命令行參數(shù)中指定了不保存文件,則該函數(shù)將直接將 TypeScript 類(lèi)型定義字符串輸出到控制臺(tái)。
const fs = require('fs-extra'); const commander = require('commander'); /** * 將 JSON 數(shù)據(jù)轉(zhuǎn)換為 TypeScript 類(lèi)型定義 * @param {Object} object - 要轉(zhuǎn)換的 JSON 對(duì)象 * @param {string} [name=JsonType] - 轉(zhuǎn)換后的類(lèi)型名稱(chēng) * @param {string} [namespace] - 轉(zhuǎn)換后的命名空間 * @returns {string} - 轉(zhuǎn)換后的 TypeScript 類(lèi)型定義字符串 */ function jsonToTs(object, name = 'JsonType', namespace) { const getType = value => { let typeRes = ``; if (Array.isArray(value)) { value.forEach(item => { let subType = getType(item); if (typeRes.split('|').indexOf(subType) < 0) { typeRes += subType typeRes += "|" } }) typeRes = typeRes.substring(0, typeRes.length - 1) return `(${typeRes})[]`; } if (typeof value === 'object' && value !== null) { const props = Object.entries(value) .map(([key, val]) => `${key}: ${getType(val)}`) .join('; '); return `{ ${props} }`; } return typeof value; }; const type = getType(object); const declaration = `interface ${name} ${type}`; return namespace ? `namespace ${namespace} { \r\n ${declaration} \r\n}` : declaration; } /** * 讀取文件并解析成 JSON 對(duì)象 * @param {string} path - 文件路徑 * @returns {Promise<Object>} - JSON 對(duì)象 */ async function readJson(path) { const content = await fs.readFile(path, 'utf8'); return JSON.parse(content); } /** * 將 TypeScript 類(lèi)型定義字符串寫(xiě)入文件 * @param {string} content - TypeScript 類(lèi)型定義字符串 * @param {string} path - 文件路徑 * @returns {Promise<void>} */ async function writeTs(content, path) { await fs.writeFile(path, content, 'utf8'); } /** * 將 JSON 數(shù)據(jù)轉(zhuǎn)換為 TypeScript 類(lèi)型定義 * @param {string} inputPath - 輸入 JSON 文件路徑 * @param {string} outputPath - 輸出 TypeScript 文件路徑 * @param {string} [options.name=JsonType] - 轉(zhuǎn)換后的類(lèi)型名稱(chēng) * @param {string} [options.namespace] - 轉(zhuǎn)換后的命名空間 * @param {boolean} [options.noFile] - 不將 TypeScript 類(lèi)型定義保存為文件 * @returns {Promise<void>} */ async function jsonToTsFile(inputPath, outputPath, options) { const { name, namespace, noFile } = options try { const object = await readJson(inputPath); const type = jsonToTs(object, name, namespace); if (noFile) { console.log(type); } else { await writeTs(type, outputPath); console.log(`Type definition saved to ${outputPath}`); } } catch (err) { console.error(err.message); } } const program = new commander.Command(); program .arguments('<input> <output>') .option('--no-file', 'do not save to file') .option('-s, --namespace <namespace>', 'type namespace') .option('-n, --name <name>', 'type name', 'JsonType') .action(jsonToTsFile); program.parse(process.argv);
六、寫(xiě)在最后
這個(gè)工具可以極大地提高在 TypeScript 項(xiàng)目中編寫(xiě)類(lèi)型聲明的效率。通過(guò)輸入一個(gè) JSON 數(shù)據(jù),它可以自動(dòng)生成對(duì)應(yīng)的 TypeScript 類(lèi)型定義,支持復(fù)雜類(lèi)型,如數(shù)組和對(duì)象,并支持自定義類(lèi)型名稱(chēng)和命名空間。此外,還可以選擇將轉(zhuǎn)換后的 TypeScript 類(lèi)型定義保存為文件。
到此這篇關(guān)于基于JS實(shí)現(xiàn)將JSON數(shù)據(jù)轉(zhuǎn)換為T(mén)ypeScript類(lèi)型聲明的工具的文章就介紹到這了,更多相關(guān)JS實(shí)現(xiàn)JSON轉(zhuǎn)TypeScript類(lèi)型聲明內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
JS+Canvas實(shí)現(xiàn)的俄羅斯方塊游戲完整實(shí)例
這篇文章主要介紹了JS+Canvas實(shí)現(xiàn)的俄羅斯方塊游戲,結(jié)合完整實(shí)例形式分析了Canvas技術(shù)實(shí)現(xiàn)俄羅斯方塊游戲的步驟、技術(shù)難點(diǎn)與相關(guān)實(shí)現(xiàn)技巧,需要的朋友可以參考下2016-12-12JavaScript 中的12種循環(huán)遍歷方法【總結(jié)】
本文給大家總結(jié)了12種JavaScript 中的1循環(huán)遍歷方法,每種方法通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2018-05-05通過(guò)構(gòu)造函數(shù)實(shí)例化對(duì)象的方法
下面小編就為大家?guī)?lái)一篇通過(guò)構(gòu)造函數(shù)實(shí)例化對(duì)象的方法。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-06-06微信小程序云開(kāi)發(fā)之使用云數(shù)據(jù)庫(kù)
這篇文章主要為大家詳細(xì)介紹了微信小程序云開(kāi)發(fā)之使用云數(shù)據(jù)庫(kù),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-05-05用javascript關(guān)閉本窗口技巧小結(jié)
window.close()是用來(lái)關(guān)閉窗口的,而且ie和firefox都是支持的,下面通過(guò)示例為大家介紹下用javascript關(guān)閉本窗口2014-09-09用javascript模仿ie的自動(dòng)完成類(lèi)似自動(dòng)完成功的表單
最近在寫(xiě)一個(gè)javascript框架,看見(jiàn)網(wǎng)上有不少自動(dòng)完成功能的表單,于是用javascript寫(xiě)了一個(gè),需要的朋友可以參考下2012-12-12