类型推导
前面我们简单介绍了下 TS 中的基本类型,但是对于初次使用 TS 的用户来说明显感觉比 JS 繁琐很多(JS 中变量不需要指定类型),难道以后每声明一个变量都需要标明类型吗?
在 TypeScript 中,不是每个地方都需要标注类型,因为类型推断允许您无需编写额外的代码即可获得大量功能。
当声明一个变量没有赋值的时候默认是 any 类型
const a; // any
默认在初始化的时候会进行类型推导
let str = 'name'; // str为string类型
str = 1; // Type 'number' is not assignable to type 'string'.
包装对象
在使用基本数据类型时,会将原始类型包装成对象类型
// 11..toString() -> Number(11).toString()
const number1:number = 11
// Number(11) 返回的是一个基本数据类型值
const number2:number = Number(11)
// 下面这样不行,不能把实例赋值给基本类型
// semantic error TS2322: Type 'Number' is not assignable to type 'number'.
'number' is a primitive, but 'Number' is a wrapper object. Prefer using 'number' when possible.
// const number3:number = new Number(11)
// 类也是一个类型,它可以描述实例
const number4:Number = new Number(11)
const number5:Number = 11
联合类型
联合类型表示赋的值是多个类型中的一个,用 |
分割每个类型。如:
let a: number | string;
a = 1;
a = '';
变量 a
可以赋值为 number
或者 string
类型,除此之外不能将其它类型的值赋值给它。如下代码会报错:
// Type 'boolean' is not assignable to type 'string | number'.
a = false;
在使用联合类型时,没有赋值时只能访问联合类型中共有的方法和属性:
let name:string | number // 联合类型
console.log(name!.toString()); // 公共方法
// 报错:Property 'toFixed' does not exist on type 'string | number'.Property 'toFixed' does not exist on type 'string'.
console.log(name!.toFixed(2)); // number方法
// 报错:bProperty 'toLowerCase' does not exist on type 'string | number'.Property 'toLowerCase' does not exist on type 'number'.
console.log(name!.toLowerCase()); // 字符串方法
// 如果我们想调用它们特定的方法,需要先给它们赋值,也就是指明这个变量到底是什么类型
name = 10;
console.log(name!.toFixed(2)); // number方法
name = 'zf';
console.log(name!.toLowerCase()); // 字符串方法
类型断言
类型断言可以用来手动指定一个值的类型。类型断言有两种形式,一种是使用 as 语法,一种是使用尖括号,但是使用尖括号的写法和JSX 语法有冲突,所以不建议使用这个写法。
const ele:HTMLElement | null = document.getElementById('#app')
ele!.style.color = 'red';
(ele as HTMLElement).style.color = 'red';
// 将ele强转成HTMLElement,这样写和JSX语法有冲突,尽量不要这么写
(<HTMLElement>ele).style.color = 'red';
// 双重断言,不建议使用,因为会破坏原有类型
(ele as unknown) as boolean
let name: string | number;
// semantic error TS2454: Variable 'name' is used before being assigned.
// (name as number).toFixed();
(name! as number).toFixed();
// 这里赋的初始值是 number 类型,下面调用的的是字符串的方法
let age: string | number = 1;
// semantic error TS2352: Conversion of type 'number' to type 'string' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first.
// (age as string).toLowerCase();
// 双重断言
(age as unknown as string).toLowerCase()
字面量类型
可以用字面量当做类型,给变量赋值时也只能采用这几个值(限定值),类似枚举。
let direction:'up'|'down'|'left'|'right'
direction = 'up'
// Type '"aaa"' is not assignable to type '"up" | "down" | "left" | "right"'
// direction = 'aaa'
如果我们还有变量 direction2、direction3…,每一个都像声明 direction 一样写未免有些麻烦,这个时候我们可以使用 type 来给类型起个别名,方便后续使用。
// 类型字面量
type Direction = 'up'|'down'|'left'|'right'
let direction2: Direction
direction2 = 'left'
联合类型
联合类型描述的值可以是几种类型之一,使用竖线 |
来分隔每个类型。举个🌰:
let a:string|number;
a 的值既可以是字符串也可以是数组。
下面这个方法,当传入的是字符串则按姓名排序,如果传入的是数字则按学号排序
function sortByType(type:string|number) {
if (typeof type == 'string') {
console.log('按姓名排序', type);
}else {
console.log('按学号排序', type);
}
}
sortByType(1)
联合类型和字面量类型的区别:
type Direction = 'up' | 'down';
type Info = string | number | boolean;
const direction: Direction = 'up';
const info1: Info = '1';
const info2: Info = '2';
const info3: Info = '3';
从上面的例子可以看出,字面量类型声明的变量可赋值的范围就那么指定的那么几个;使用联合类型声明的变量可赋值的种类更多。