如何不使用tsc编译来执行TypeScript代码
「这是我参与2022首次更文挑战的第1天,活动详情查看:2022首次更文挑战」。
Dear,大家好,我是“前端小鑫同学”,😇长期从事前端开发,安卓开发,热衷技术,在编程路上越走越远~
通常在编写完TypeScript代码以后总是需要通过其内置的CLI来编译为JavaScript文件,再通过node来执行,当然也有简化操作的库,如:ts-node。下面就来探索一下如何实现类似ts-node可以直接执行TypeScript的功能吧。
前提概要:
1. 涉及知识点:
- NodeJs:require函数
- TypeScript:Compiler API
2. 任务拆解:
- 如何让Node认识Ts文件;
- 如何让Ts文件变为Js文件。
3. require函数的执行过程: module.js
- Module.prototype.require(path):
- 根据传入path来确定待加载模块的绝对路径;
- 执行模块加载(顺序:1. 优先缓存,2. 内置模块,3. 生成实例并存入缓存)
- Module.prototype.load(filename):
- 通过文件名称识别后缀为.js,.json,.node的文件并读取内容;
- 通过Module内置的_compile函数进行模块化编译。
如何识别ts文件:
- module中如何识别js文件:
Module._extensions['.js'] = function(module, filename) { var content = fs.readFileSync(filename, 'utf8'); module._compile(stripBOM(content), filename); };
- 仿照module的源码处理来实现识别ts文件:
const fs = require('fs'); require.extensions['.ts'] = function (module, filename) { var content = fs.readFileSync(filename, 'utf8'); console.log(filename); console.log(content); }; require('./index.ts')
将TypeScript代码转义为JavaScript代码,下图为Ts Compiler API的Wiki内容截图提供了最简单的实现API:
const ts = require('typescript'); // 编译前的Ts内容 const content = ` enum PersonType { MAN = 1, WOMAN = 2, } if (PersonType.MAN === 1) { console.log('hello ts'); } `; const { outputText } = ts.transpileModule(content, { compilerOptions: { module: ts.ModuleKind.CommonJS } }) // 编译后的Js内容: /* var PersonType; (function (PersonType) { PersonType[PersonType["MAN"] = 1] = "MAN"; PersonType[PersonType["WOMAN"] = 2] = "WOMAN"; })(PersonType || (PersonType = {})); if (PersonType.MAN === 1) { console.log('hello ts'); } */ console.log(outputText);
Ts执行器完整代码:
// ts-actuator.js const path = require('path'); const fs = require('fs'); const ts = require('typescript'); // 从命令行获取下标为2的参数(待执行的ts文件名称) const filePath = process.argv[2]; // 增加支持.ts文件后缀的检测 require.extensions['.ts'] = function (module, filename) { // 得到绝对ts文件的路径并读取内容 const fileFullPath = path.resolve(__dirname, filename); const content = fs.readFileSync(fileFullPath, 'utf-8'); // 通过Ts提供的transpileModule将Ts字符串转为Js字符串 const { outputText } = ts.transpileModule(content, { compilerOptions: { module: ts.ModuleKind.CommonJS } }) // 将得到的Js字符串进行模块编译 module._compile(outputText, filename); } // 执行模块的require函数 require(filePath);
结语:
看了光哥的文章,自己写了两遍找了找感觉,很神奇,光哥的文章地址:手写一个 ts-node 来深入理解它的原理
欢迎关注我的公众号“前端小鑫同学”,原创技术文章第一时间推送。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)