前序:为什么要用ts?
答:js过于灵活,小项目&小团队中灵活是一种优势,指哪打哪,但较大项目,且多人合作开发场景下,过于灵活反而是一种劣势。举个例子,此次开发任务是对已离职同事的某一项业务进行二次开发:
function fn(index, name, age) {
if (......) {
return arg[0]
} else if (......) {
return arg[1]
}
return arg[2]
}
分析如上代码,首先我们要找到fn函数的入参,再分析一遍此函数执行过程后才可以介入修改,如果有类型标注函数会更加直观
function fn(index: number, name: string, age: number): string | number {
if (......) {
return arg[0]
} else if (......) {
return arg[1]
}
return arg[2]
}
TypeScript 类型系统中的类型
静态类型系统的目的是把类型检查从运行时提前到编译时,那 TS 类型系统中肯定要把 JS 的运行时类型拿过来,也就是 number、boolean、string、object、bigint、symbol、undefined、null 这些类型,还有就是它们的包装类型(基本数据类型的对象引用类型) Number、Boolean、String。
这些很容易理解,给 JS 添加静态类型,总没有必要重新造一套基础类型吧,直接复用 JS 的基础类型就行。
复合类型方面,JS 有 class、Array,这些 TypeScript 类型系统也都支持,但是又多加了三种类型:元组(Tuple)、接口(Interface)、枚举(Enum)。
元组
元组(Tuple)就是元素个数和类型固定的数组类型:
let myTuple: [number, string] = [1, "Hello"];
myTuple被定义为一个元组,它包含一个number类型的元素和一个string类型的元素,且元素的顺序是固定的。
使用场景
1.函数返回多个值
2.任何需要固定长度和类型的数组场景。
与数组的对比
1.元祖的长度是确定的,且每个元素的类型声明时就已确认 2.数组长度是可变的,元素类型是任意的
使用注意事项
长度固定::一旦定义了元组的结构,添加或移除元素,或者改变元素的顺序,都会导致编译时错误
类型固定:元组中每个位置的元素类型是预定义的,赋予不匹配的类型值会引发错误。
解构与访问:可以通过解构或索引来访问元组中的元素,但是访问超出其长度的索引将会是undefined,且会导致类型安全问题
可变性:默认情况下,元组是可变的,即可以修改元组中元素的值(但不能改变元素的类型或增减元素)。如果需要不可变元组,可以使用readonly修饰符。
接口
接口(Interface)可以描述函数、对象、构造器的结构:
interface IPerson {
name: string;
age: number;
}
const obj: IPerson = {
name: '',
age: 1
}
在TypeScript中,接口(Interfaces)是一种设计用来定义对象的结构的方式。接口可以被用来类型检查,确保一个对象只有当它包含特定的结构时才能被接受。它们非常类似于其他编程语言中的接口或抽象类。
接口主要有以下几种用途:
- 定义对象的结构:你可以定义一个接口来描述一个对象应该有哪些属性和方法。
- 类型检查:TypeScript 编译器会使用接口来确保一个对象符合接口定义的结构。
- 多态:接口允许你使用不同的对象,只要它们符合相同的接口定义。
枚举
枚举(Enum)是一系列值的复合:
enum Transpiler {
Babel = 'babel',
Postcss = 'postcss',
Terser = 'terser',
Prettier = 'prettier',
TypeScriptCompiler = 'tsc'
}
const transpiler = Transpiler.TypeScriptCompiler;