一、概述
TypeScript 定义变量类型的语法格式:
let 变量名:变量类型 = 值;
但我们为某个变量定义了类型之后,改变了只能赋予指定类型的值,否则会报错。
二、原始数据类型
JavaScript 的类型分为两种:原始数据类型(Primitive data types)和对象类型(Object types)。
原始数据类型包括:boolean、number、string、null、undefined 以及 ES6 中的新类型 Symbol。
// 1. 布尔类型let isLogin: boolean = true;// 2. 数值类型let age: number = 18;// 3. 字符串类型let job: string = "前端工程师";// 4. 空值:一般用于函数返回值为空的情况function sayHello(): void {console.log("Hello");}// 5. null & undefinedlet u:undefined = undefined;let n: null = null;// 6. symbollet s = Symbol();
三、特殊类型
1. any
any 用来表示允许赋值为任意类型。我们在知道,在TS中,如果一个变量被赋予了一个类型,就不能再赋予其他类型的值了,如果为任意类型,则可以赋予任何类型的值。
let message: any;
message = "TypeScript是JavaScript的超集!";
message = 123;
message = false;
message.split(''); // 控制台输出:message.split is not a function
提示:
- 变量如果在声明的时候,未指定其类型,那么它会被识别为任意值类型,一般用于获取DOM。
any是 TypeScript 中的顶级类型,使用any,基本上放弃了类型检查,因此开发中会引起不必要的麻烦。比如上述示例中,访问split方法抛出异常。所以,一般情况下不建议使用any类型。
2. unknown
unknown 是TypeScript 3.0中引入的,也被认为是顶级类型,但它更安全,与 any 一样,所有类型都可以分配给 unknown。
let message: unknown;
message = "TypeScript是JavaScript的超集!";
message = 123;
message = false;
message.split(''); // TS语法检测:Object is of type 'unknown'.
可以发现,在使用 any 定义类型时,调用 split 方法并不会出发TS的语法检测,而使用 unknown 时,TS会捕捉到问题并予以提示。
3. void
某种程度上来说,void 类型像是与 any 类型相反,它表示没有任何类型。 当一个函数没有返回值时,你通常会见到其返回值类型是 void:
function run():void {
console.log("I'm running!");
}
声明一个 void 类型的变量没有什么大用,因为你只能为它赋予 undefined 和 null
4. never
never 类型表示的是永不存在的值得类型,比如:
// -- 返回never的函数必须存在无法达到的终点
function error(message: string): never {
throw new Error(message);
}
// -- 推断的返回值类型为never
function fail() {
return error("Something failed");
}
// -- 返回never的函数必须存在无法达到的终点
function loop(): never {
while (true) {
}
}
四、联合类型
联合类型表示可以为变量定义多个类型,比如:
let age: number | string;
age = 10;
age = '10';
上述示例示例中,变量 age 被定义成联合类型,可以赋值 number 类型 或者 string 类型的值。
通常在使用 age 变量时,为了更安全的使用,我们可以通过如下方法判断其具体类型之后进行相应的操作。
五、类型断言
类型断言(Type Assertion)可以用来手动指定一个值的类型。语法形式如下:
<Value>TypeValue as Tpe
示例:
let _name: unknown = "木子李";
let len: number = (_name as string).length;
let len: number = (<string>_name).length;
六、类型推断
如果没有明确的指定类型,那么 TypeScript 会推断出一个类型。
let hello = "Hello, TypeScript!";
hello = 10; // Type 'number' is not assignable to type 'string'.
提示:如果定义的时候没有赋值,不管之后有没有赋值,都会被推断成
any类型而完全不被类型检查。
七、类型别名
类型别名用来给一个类型起个新名字:
// 为 string 类型定义别名 LString;
type LString = string;
// 定义变量,指定类型为 LString(实际为 string 类型)
let message: LString;
message = 'Are you ok?';
message = 10; // Type 'number' is not assignable to type 'string'.
类型别名对于一些联合类型或者复杂类型比较有用,可以使其更加简洁,比如:
// 定义用户类型
type UserType = {
name: string;
age: number;
job: string;
}
// 定义年龄类型
type AgeType = string | number;
let user: UserType = {
name: "Li-HONGYAO",
age: 18,
job: '前端工程师'
}
let age: AgeType = user.age;
八、字面量类型
type LoginType = "用户名" | "邮箱" | "手机号";
let _type: LoginType;
_type = "手机号";
_type = "邮箱";
_type = "用户名";
_type = "微信"; // Type '"微信"' is not assignable to type 'LoginType'.
上例中,我们使用 type 定了一个字符串字面量类型 _type,它只能取三种字符串中的一种。
注意,类型别名与字符串字面量类型都是使用
type进行定义。
九、数组
let arr1: number[] = [1, 2, 3];
let arr2: (string | number)[] = [1, 'A', 2];
let arr3: Array<number> = [1, 2, 3];
提示:数组在声明时确定元素类型之后数组元素只能是对应的数据类型,除非将数组元素类型指定为
any。
十、元祖(Tuple)
元组类型允许表示一个 已知元素数量和类型 的数组,各元素的类型不必相同:
let foo: [string, number];
foo = ["Li-HONGYAO", 18];
foo = [18, "Li-HONGYAO"]; // Type 'string' is not assignable to type 'number'.
解构元祖:
let [uname, age] = ["Li-HONGYAO", 18];
console.log(uname); // Li-HONGYAO
console.log(age); // 18
