对于前端工程师来说,使用 typescript 开发无疑就是在尝试换一种思维方式做事情, 使用它,会影响我写代码时的思考方式。
TS 怎么影响了我的思考方式
\
对前端开发者来说,TS 能强化了「面向接口编程」这一理念。我们知道稍微复杂一点的程序都离不开不同模块间的配合,不同模块的功能理应是更为清晰的,TS 能帮我们梳理清不同的接口
明确的模块抽象过程
\
TS 对我的思考方式的影响之一在于,我现在会把考虑抽象和拓展看作写一个模块前的必备环节了。当然一个好的开发者用任何语言写程序,考虑抽象和拓展都会是一个必备环节,不过如果你在日常生活中使用过清单,你就会明白 TS 通过接口将这种抽象明确为具体的内容的意义所在了,任何没有被明确的内容,其实都有点像是可选的内容,往往就容易被忽略。
使用 TS 的过程就是一种学习的过程
\
使用 TS 后,感觉自己通过浏览器查文档的时间明显少了很多。无论是库还是原生的 js 或者 nodejs,甚至是自己团队其它成员定义的类型。结合 VSCode ,会有非常智能的提醒,也可以很方便看到相应的接口的确切定义。使用的过程就是在加深理解的过程,确实「面向接口编程」天然和静态类型更为亲密。
一些 TS 中的新概念
\
编程实际上就是对数据进行操作和加工的过程。类型系统能辅助我们对数据进行更为准确的操作。TypeScript 的核心就在于其提供一套类型系统,让我们对数据类型有所约束。约束有时候很简单,有时候很抽象
TS 支持的类型如下:boolean,number,string,[],Tuple,enum,any,void,null,undefined,never,Object。
TS 中更复杂的数据结构其实都是针对上述类型的组合,关于类型的基础知识,推荐先阅读基础类型一节,这里只讨论最初对我造成困扰的概念:
enum: 现在想想 enum 枚举类型非常实用,很多其它的语言都内置了这一类型,合理的使用枚举,能让我们的代码可读性更高,比如
const enum MediaTypes {
JSON = "application/json"
}
fetch("https://swapi.co/api/people/1/", {
headers: {
Accept: MediaTypes.JSON
}
})
.then((res) => res.json())
\
never: never 代表代码永远不会执行到这里,常常可以应用在 switch case 的 default 中,防止我们遗漏 case 未处理,比如:
enum ShirTSize {
XS,
S,
M,
L,
XL
}
function assertNever(value: never): never {
console.log(Error(`Unexpected value '${value}'`));
}
function prettyPrint(size: ShirTSize) {
switch (size) {
case ShirTSize.S: console.log("small");
case ShirTSize.M: return "medium";
case ShirTSize.L: return "large";
case ShirTSize.XL: return "extra large";
default: return assertNever(size);
}
}
下面是上述代码在我的编辑器中的截图,编辑器会通过报错告知我们还有未处理的情况
\
- 类型断言: 类型断言其实就是你告诉编译器,某个值具备某种类型。有两种不同的方式可以添加类型断言:
- someValue
- someValue as string
关于类型断言,我看文档时的疑惑点在于,我想不到什么情况下会使用它。后来发现,当你知道有这么一个功能,在实际使用过程中,就会发现能用得着,比如说迁移遗留项目时。
- Generics(泛型): 泛型让我们的数据结构更为抽象可复用,因为这种抽象,也让它有时候不是那么好理解。泛型的应用场景非常广泛,比如:
type Nullable<T> = {
[P in keyof T]: T[P] | null;
};
能够让某一种接口的子类型都可以为 null。我记得我第一次看到泛型时也觉得它很不好理解
Typescript的优点及不足
优点:
- 清晰的函数参数/接口属性,增加了代码可读性和可维护性
- 静态检查
- 生成API文档
- 配合现代编辑器,各种提示
- 活跃的社区
不足:
- 写代码额外的标记类型声明
- 和某些库结合的不是很完美