ts在js的基础上新增了any、unknown、void、never、元组(tuple)、枚举(num)数据类型。
1,any类型
在某些情况下,我们确实无法确定一个变量的类型并且可能它随时会发生一些变化,这个时候我们可以使用any类型,any类型有点像一种讨巧的typeScript手段:
(1)我们可以对any类型的变量进行任何的操作,包括获取不存在的属性、方法。
(2)我们也可以给一个any类型的变量赋任何的值,比如数字、字符串的值。
如果对于某些情况的处理过于繁琐不希望添加规定的类型注解或者在引入一些第三方库时缺失类型注解,这个时候我们可以使用any,包括在Vue源码中,也会使用到any来进行某些类型的适配。
let message: any = "Hello World"
message = 123
message = true
message = {}
console.log(message)
2,unknown类型
unknown类型是typeScript中比较特殊的一种类型,它用于描述类型不确定的变量。
function foo() {
return "abc"
}
function bar() {
return 123
}
let flag = true
//定义result变量用于接受不同函数的返回值,那么在这里也就导致了我们在定义变量时无法确定该变量的类型
let result: unknown // 最好不要使用any
if (flag) {
result = foo()
} else {
result = bar()
}
//这里演示的是:unknown和any数据类型的区别
let message: any = result
// let message: number = result //会报错
let num: unknown = result
console.log(result)
注意:unknown和any数据类型的区别:unknown类型只能再次赋值给any和unknown类型,而any类型可以再次赋值给任意类型。
3,void类型
void类型通常用来指定一个函数如果是没有返回值的,那么它的返回值就可以设置为void类型。
4,never类型
never类型表示永远不会有返回值的类型,常见的有以下几种情况:
(1)如果函数是一个死循环,那么它永远也不会有返回值。
function foo(): never {
// 死循环是永远不会有返回值的
while(true) {}
}
(2)或者抛出一个异常也是永远不会有返回值的。
function bar(): never {
throw new Error()
}
(3)还有一个常用的应用场景:要求后续调用者如果想要传入其他的数据类型时,必须添加上相应的判断逻辑,否则在后面所添加的never类型就会报错。
//如果想给参数添加其他的数据类型boolean
function handleMessage(message: string | number | boolean) {
switch (typeof message) {
case 'string':
console.log("string处理方式处理message")
break
case 'number':
console.log("number处理方式处理message")
break
//那么必须添加相应的boolean逻辑判断,因为在所有判断的最后default中,我设置了never类型,所以要想有返回值,则必须添加上相对应的逻辑判断。
case 'boolean':
console.log("boolean处理方式处理message")
break
default:
const check: never = message
}
}
handleMessage("abc")
handleMessage(123)
handleMessage(true)
5,tuple元组类型
学习元组类型之前,先来学习下数组类型,数组类型有以下两种写法:
const names1: Array<string> = [] // 不推荐,在react中写jsx时有冲突
const names2: string[] = [] // 推荐,自己也是常使用的这种方式
其次,数组中通常建议存放相同类型的元素,不同类型的元素是不推荐放在同一数组中的,如果非要将不同类型的元素放在同一数组中的话,那么便可以使用元组tuple类型来进行存放,从而使每个元素都有自己特定的类型。使用元组tuple类型时我们可以根据索引值获取到的值可以确定对应的类型,避免误操作。
const info: [string, number, number] = ["why", 18, 1.88]
const name = info[0] //一定是string类型
console.log(name.length) //那么这时便可以访问它的length属性了,而这正是typescript的一大好处
6,enum枚举类型
枚举类型是为数不多的TypeScript所特有的特性之一,枚举其实就是将一组可能出现的值一个个列举出来,定义在一个类型中,这个类型就是枚举类型,而且枚举类型允许开发者定义一组命名常量,常量可以是数字、字符串类型。
enum Direction {
LEFT,
RIGHT,
TOP,
BOTTOM
}
function turnDirection(direction: Direction) {
switch (direction) {
case Direction.LEFT:
console.log("改变角色的方向向左")
break;
case Direction.RIGHT:
console.log("改变角色的方向向右")
break;
case Direction.TOP:
console.log("改变角色的方向向上")
break;
case Direction.BOTTOM:
console.log("改变角色的方向向下")
break;
default:
const foo: never = direction;
break;
}
}
turnDirection(Direction.LEFT)
turnDirection(Direction.RIGHT)
turnDirection(Direction.TOP)
turnDirection(Direction.BOTTOM)
这里还需要稍微注意一下枚举类型的值,枚举类型的默认值是从0开始的, 当然,我们也可以给枚举类型的每一个值赋予指定的数字类型或者只赋予第一个值为数字100,那么这个时候便会从100进行递增,当然我们也可以给他赋值字符串类型。
数据类型补充
1,类型断言
有时候TypeScript无法获取具体的类型信息,这个时候我们便需要使用类型断言as,比如我们通过 document.getElementById,TypeScript只知道该函数会返回 HTMLElement ,但并不知道它具体的类型。
const el = document.getElementById("why") as HTMLImageElement
el.src = "url地址"
2,非空类型断言
当我们编写下面的代码时,在执行ts的编译阶段会报错,这是因为传入的message有可能是为undefined的,这个时候是不能执行方法的。
function printMessageLength(message?: string) {
console.log(message.length)
}
但是,我们确定传入的参数是有值的,这个时候我们便可以使用非空类型断言,非空类型断言使用的是 ! ,表示可以确定某个标识符是有值的,跳过ts在编译阶段对它的检测。
function printMessageLength(message?: string) {
console.log(message!.length)
}
printMessageLength("aaaa")
3,可选链的使用
可选链事实上并不是TypeScript独有的特性,它是ES11(ES2020)中增加的特性,可选链使用可选链操作符 ?.,它的作用是当对象的属性不存在时,会短路,直接返回undefined,如果存在,那么才会继续执行,虽然可选链操作是ECMAScript新提出的特性,但是typescript也可以使用。
type Person = {
name: string
friend?: {
name: string
age?: number,
girlFriend?: {
name: string
}
}
}
const info: Person = {
name: "why",
friend: {
name: "kobe",
girlFriend: {
name: "lily"
}
}
}
console.log(info.name)
console.log(info.friend?.name)
console.log(info.friend?.age)
console.log(info.friend?.girlFriend?.name)
4,??和!!的使用
有时候我们还会看到 !! 和 ?? 操作符,这些都是做什么的呢?
!!操作符:将一个其他类型转换成boolean类型,类似于Boolean(变量)的方式。
??操作符:它是ES11增加的新特性,空值合并操作符(??)是一个逻辑操作符,当操作符的左侧是 null 或者 undefined 时,返回其右侧操作数,否则返回左侧操作数。
const message = "Hello World"
// const flag = Boolean(message)
// console.log(flag)
const flag = !!message
console.log(flag)
let message: string|null = "Hello World"
const content = message ?? "你好啊, 李银河"
// const content = message ? message: "你好啊, 李银河"
console.log(content)
当然你还会想到有其他的类型,我把它们放在函数中去总结,因为那样更容易理解一点。