前言
作为一个前端同学,为什么不用JavaScript刷LeetCode,而是使用TypeScript来刷题呢?
当然,你也可以选择c++、java来刷题,但我认为还是用自己研究方向的语言比较好,也可以加深语言理解。
主要是JavaScript刷题体验太糟糕了,弱类型语言,不支持类型注解,语法太松散,放在做项目不合适,用来刷算法也让人诟病。
- 弱类型语言,
JavaScript全是any类型,必须写一大坨的JSDoc,才能让编辑器知道类型,否则无法提示一个复杂数据类型的属性和方法。
思考下面的,你能发现什么区别吗?为什么会出现这种情况


JavaScript没有编译时检查,代码错误只会在运行时检查,语言太松散,只要不是什么词法和语法上的错误,怎么写都不会报错!!!,比如像给const声明的常量再赋值、随意给函数传参、随意调用对象不存在的属性和方法添等等,这些在编写时都不会报错,只有在运行时才会报错,我都无力吐槽了。
就这两大难以忍受的槽点,我就觉得必须要换门语言了。
可以看下面写的,我乱写都不报错,leetcode上写体验也一样。。。
但是,这些在TypeScript上统统得到解决
接下来,我将用VSCode搭建一个集运行和调试的TypeScript刷题环境。
疑问:为什么我不直接在leetcode网站上直接刷题呢?
答:leetcode上不能debug(或者说要收费),并且leetcode上只能做leetcode上的题目,其他地方的就不能做了,像牛客上的,还有就是我们可以根据自己需要去分类管理自己刷的题目,写在本地的也可以放在代码仓库。缺点就是我们在VSCode写完了,要copy到leetcode网站上去测试,不过也不麻烦。
我是非常推荐前端同学转用TypeScript刷题的,TypeScript是JavaScript的一个超集,语言的灵魂还是JavaScript。
其实刷题用到语法是很朴素的,用不到太深入的语言功底,在我看来,你只要有JavaScript基础,再会些TypeScript的类型和一点点泛型知识,就可以应对算法用到的语言基础了。
环境准备
不同于JavaScript,我们运行和调试TypeScript需要用到npm,我们需要借助ts-node和typescript这两个包,通过npm来安装它们。
目前我Node.js版本:v18.13.0,npm版本:v8.4.0。
新建一个文件夹,作为项目根目录,这里我建了个typescript-leetcode
首先,初始化package.json
npm init -y
通过npm安装ts-node和typescript
提示:很多人可能全局安装了
ts-node和typescript,但全局的不行,必须使用项目下的依赖
npm i ts-node typescript
然后在根目录下新建src,用来存放我们编写的源代码,我们可以写一个ts程序。
添加运行和调试配置
可以先看看我之前写的:使用VSCode内置的JavaScript Debug Terminal来调试JavaScript。
重复的内容我就不说了,说下区别,nodejs是不能直接运行TypeScript的,需要通过tsc编译为js,然后在运行js,这样相当麻烦,我们的目标是直接运行和调试ts,我们可以用ts- node,原理也是一样的,不过只是ts-node内部帮我们做了ts转js这个过程,不需要额外生成js。
可以看看和之前launch.json的区别。
{
// 使用 IntelliSense 了解相关属性。
// 悬停以查看现有属性的描述。
// 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"type": "node",
"request": "launch",
"name": "Launch TS",
"runtimeArgs": ["-r", "ts-node/register"],
// "console": "integratedTerminal",
"internalConsoleOptions": "openOnSessionStart",
"skipFiles": ["<node_internals>/**"],
"program": "${workspaceFolder}/${file}"
}
]
}
变量命名冲突
刚开始都会踩的一个坑,无法重新声明块范围变量“arr”。ts(2451),原因在于同一个文件夹下,其他文件也有同名的变量声明。
去查了下,在 Commonjs 规范里,没有像 ESModule 能形成闭包的「模块」概念,所有的模块在引用时都默认被抛至全局,因此当再次声明某个模块时,TypeScript 会认为重复声明了两次相同的变量进而抛错。
解决方案很简单,只要在让这个文件成为一个模块即可,只要在文件中出现import、export等模块关键字即可。
我的解决方案是在 function前加个默认导出export default,这样看起来比较舒适,写起来也不麻烦。
/**
* 两数之和
* @param nums
* @param target
* @returns
*/
export default function twoSum(nums: number[], target: number): number[] {
// 定义一个map,记录之前遍历的值,key: nums[i]; value: i
const map = new Map<number, number>();
for (let i = 0; i < nums.length; i++) {
const x = target - nums[i];
if (map.has(x)) return [map.get(x)!, i];
map.set(nums[i], i);
}
return [];
}
const arr = [2, 7, 11, 15];
console.log(twoSum(arr, 9));
开启调试
接下来,我们试试怎么运行和调试,按F5启动调试,Ctrl+ F5以调试模式运行。
调试小tip
我们有时调试会发现,当我们代码结束的时候,程序会进入ts-node/register程序中,这更调试JavaScript还是有些不一样的
但是我们不想进入这里,想直接结束,这里我有发现一个小技巧,我们在代码末尾打上一个debugger语句,当我们代码执行到这debugger这行的时候,直接按F5结束调试。这也是我为什么在末尾加debugger的原因,可以进行一个卡点。
配置tsconfig.json
接下来我们要开始配置typescript的检查规则,我们在项目根目录下创建一个tsconfig.json文件,加入以下内容,这是我目前的配置,可以根据自己的需要更改。
{
"compilerOptions": {
"target": "ESNext", // 指定 ECMAScript 目标版本
"module": "NodeNext", // 指定模块标准
"lib": ["ESNext"], // 指定要包含在编译中的库文件
"strict": true, // 启用所有严格的类型检查选项
"strictNullChecks": false, // 启用严格的空(undefined、null)检查”
"noImplicitReturns": true, // 不是函数中的所有代码路径都返回值时报告错误
"noFallthroughCasesInSwitch": true, // 在 switch 语句中报告失败情况的错误
"forceConsistentCasingInFileNames": true // 禁止对同一文件的大小写不一致的引用
},
"exclude": ["node_modules"]
}
这里我要额外说点,把"strict": true打开,然后一定要关闭"strictNullChecks": false,不要问我为什么要关闭strictNullChecks,去做些leetcode上链表和二叉树相关的题目,真的是让我苦不堪言。
主要是涉及null这个类型,TypeScript的类型推导确实非常强大,但它很多时候还是不能理解你整个代码逻辑的,所以如果你开了strictNullChecks,莫名其妙就爆红线,你要经常加上非空断言!符号,代码看上去非常怪。在leetcode网站上也是关掉了这个strictNullChecks的。
但如果是在实际项目开发中,还是建议开启strictNullChecks。
Node环境支持
如果你要写Nodejs相关的东西,你需要安装@types/node,否则你没有安装相关库的声明文件,使用Nodejs相关的api会报错。
npm i --save @types/node
规范代码风格
我们也可以给项目添加代码风格规范,比如prettier,用来规范我们的代码风格
在项目的根目录下创建.prettierrc,前提你要在VSCode安装prettier插件。在文件中写入
{
"printWidth": 120,
"tabWidth": 2,
"semi": true,
"singleQuote": false,
"arrowParens": "always",
"endOfLine": "auto"
}
最终,项目结构
正确使用TypeScript
刚开始用ts难免会遇到些坑,尤其是类型注解使用的疑问,我也是踩着坑过来的。
文章偏长,所以我单独写一篇博客:TS刷leetcode的一些使用心得分享
希望能少走点弯路。
🍬最后
写这么多,到这结束了。我刚开始用JavaScript,后转到TypeScript刷题,截止目前,我用TypeScript刷了也有七八十道题了,体验相当好。
我还把我刷的leetcode题分类整理上传到github上了,感兴趣可以去我的仓库看看:🚀🚀🚀typescript-algorithms。
遇到不会的地方,可以参照我的写法,觉得不错的也可以给我的仓库点个星星⭐️⭐️,我也一直有在刷题,仓库也会一直更新。
关于leetcode上的TypeScript题解,由于TypeScript语言比较新,用的人少,所以题解也比较少,但JavaScript的题解是比较多的,你完全可以根据JavaScipt题解写出TypeScript题解,也可以去看看c++、java题解,很多都讲的非常不错,算法能用到语法都是非常朴素的,看懂很容易,我一直都觉得做算法就是用最朴素的语法写出最晦涩的逻辑。
再来分享下我经常看的刷题网站
如果有什么问题,可以在评论区讨论,我也会去解答,也可以分享我的刷题经验,最后,创作不易,可以点赞支持一下🥰🥰