作为前端开发者,我们都知道JavaScript是一门弱语言,它的类型是可以动态发生改变的,由此会导致一些较为隐蔽的错误。而TypeScript作为JS的超集,核心功能就是在编译时将类型错误找出来,可以节省相当多的时间,同时也有利于项目的维护与拓展。为了方便的使用它,我们就需要了解它的功能与特性。
安装TypeScript
要使用typescript就需要先安装,通过npm安装:
npm install -g typescript
构建一个TypeScript文件
新建一个 hello.ts
文件,输入以下代码:
const user: string = 'Jack'
function call(name: string): void {
console.log(`Hello, ${name}`);
}
call(user)
在上面代码中,我们加入了TS的类型注解
,然后使用tsc命令
将ts文件编译成js文件:
tsc hello.ts
编译后的js代码如下:
var user = 'Jack';
function call(name) {
console.log("Hello, ".concat(name));
}
call(user);
好了,到这已经学会了TS的基本使用,下面就要了解TS的基础类型。
基础类型
TS支持与JS几乎相同的数据类型,此外还提供了实用的枚举类型方便我们使用。
字符串
在上面的代码中我们给变量user
加了类型注解string
,规定了user的数据类型只能是字符串,如果是其他类型则会报错:
let user: string = 'Jack'
user = [0, 1, 2]
如图所示,数组类型不能赋值给字符串类型,如果user确实需要赋值成数组,那你可以使用联合类型
:
let user: string | number[] = 'Jack'
user = [0, 1, 2]
此时就不会报错,编译也能正常运行。联合类型本文不会涉及,在之后的学习中讨论。
布尔值 boolean
和JS中一样,布尔值就是 true/false
值:
let flag: boolean = false;
flag = true
数字 number
和JS中一样,所有数字都是浮点数。支持二进制、八进制、十进制和十六进制字面量。
let decLiteral: number = 6;
let hexLiteral: number = 0xf00d;
let binaryLiteral: number = 0b1010;
let octalLiteral: number = 0o744;
数组 Array
Ts中有两种方式可以定义数组,第一种,可以在元素类型后面接上 [],表示由此类型元素组成的一个数组:
let ary: number[] = [0, 1, 2]
第二种方式是使用数组泛型,Array<元素类型>
:
let ary: Array<number> = [0, 1, 2]
元组 Tuple
元组类型允许表示一个已知元素数量和类型
的数组,各元素的类型不必相同。 比如,你可以定义一对值分别为 string 和 number 类型的元组。
// 初始化成功
let tuple: [string, number] = ['1', 2]
// 初始化失败,类型不匹配
let tuple2: [string, number] = [1, '2']
当你给元组添加元素时,元素的类型会使用联合类型替代:
let tuple: [string, number] = ['1', 2]
tuple.push('3') // 可以,类型为(string | number)
tuple.push(false) // 不可以,布尔值不是(string | number)类型
枚举 enum
枚举是对JavaScript标准数据类型的一个补充:
// 默认情况下,从0开始为元素编号
enum Color {Red, Green, Blue}
let c: Color = Color.Green; // Green为1
你也可以手动的指定成员的数值:
enum Color {Red = 1, Green, Blue}
let c: Color = Color.Green; // Green为2
你还可以通过枚举的值得到它的名字:
enum Color {Red = 1, Green, Blue}
let colorName: string = Color[2];
console.log(colorName); // 因为Green的值是2,所以colorName为Green
any
有时候,我们会想要为那些在编程阶段还不清楚类型的变量指定一个类型。 这些值可能来自于动态的内容,比如来自用户输入或第三方代码库。 这种情况下,我们不希望类型检查器对这些值进行检查而是直接让它们通过编译阶段的检查。 那么我们可以使用 any类型来标记这些变量:
let notSure: any = 4;
notSure = "maybe a string instead";
notSure = false;
对现有代码进行改写的时候可以用到,其他情况尽量不要使用,不然就失去了使用TS的意义(类型检查)。
void
void表示没有任何类型,当一个函数没有返回值时就可以使用它:
function fn(): void {
console.log("void");
}
声明一个void类型的变量没有什么大用,因为你只能为它赋予undefined
和null
:
let unusable: void = undefined;
null 和 undefined
TypeScript里,undefined 和 null 两者各自有自己的类型分别叫做 undefined 和 null。 和 void相似,它们的本身的类型用处不是很大:
// 不能给它们赋其他值了
let u: undefined = undefined;
let n: null = null;
默认情况下null和undefined是所有类型的子类型
。 就是说你可以把 null和undefined赋值给number类型的变量。但是这会导致一些常见的类型问题,因此应该尽可能地使用 --strictNullChecks
标记,它会使 null 和 undefined 只能赋值给 void 和它们自己。
never
never
类型表示的是那些永不存在的值的类型。例如, never
类型是那些总是会抛出异常或根本就不会有返回值的函数表达式或箭头函数表达式的返回值类型; 变量也可能是 never
类型,当它们被永不为真的类型保护所约束时。
never
类型是任何类型的子类型,也可以赋值给任何类型;然而,没有类型是never
的子类型或可以赋值给never类型(除了never
本身之外)。 即使 any
也不可以赋值给never
。
下面是一些返回never类型的函数:
// 返回never的函数必须存在无法达到的终点
function error(message: string): never {
throw new Error(message);
}
// 推断的返回值类型为never
function fail() {
return error("Something failed");
}
// 返回never的函数必须存在无法达到的终点
function infiniteLoop(): never {
while (true) {
}
}
具体使用场景可以参考知乎回答
object
object
表示非原始类型,也就是除number
,string
,boolean
,symbol
,null
或undefined
之外的类型。
let obj: object = {} // ok
let obj2: object = 1 // error
let obj3: object = '2' // error
let obj4: object = false // error
let obj5: object = null // error
注意:Object(首字母大写) 和 object(首字母小写)不是一回事:
// Object 是接口,包含原始类型
let obj: Object = 4;
// object 是类型,不含原始类型
let obj2: object = {}