开启ts学习之路,本篇ts的复杂数据类型、字面量类型、返回值类型、剩余参数和this。
一、复杂数据类型
同JS一样,TS也有复杂数据类型,包含以下几种:
- 数组类型Array
- 元组类型Tuple
- 特殊类型any、unknown、void、undefined、null、never、object
接下来将围绕这几种数据类型进行讲解。
1、数组类型Array
一个数组的每一项其实是可以定义它的字段类型的:
let arr1: number[] = [1,2,3]
let arr2: string[] = ["1", "2", "3"]
如果没有按规定赋值,就会报错:
以上代码也可以用这种方式表示:
let arr1: Array<Number> = [1,2,3]
let arr2: Array<String> = ["1", "2", "3"]
注意:
建议优先使用第一种方式书写,否则在React的JSX语法中可能会冲突。下文中所有可以使用这类写法的,都不会讲。
之后所有数组的操作也必须符合以上的数据类型定义:
let arr2: string[] = ["1", "2", "3"]
arr2.push("4"); // 正确
arr2.push(4); // 错误
2、类型推断
如果每个数组项都是不同的值,TS会自动给我们提示:
这就是类型推断。TS帮我们推断出这个数组共有多少种数据类型,因此可以修改代码为:
let arr: (string | number | boolean)[] = ["小杨", 18, true]
如此,开发者便可以较为智能的书写代码。
3、元组类型Tuple
如果数组中的每一项也是个数组,应该怎么写呢?这时候就需要依赖元组Tuple。
元组最重要的特性是可以限制数组元素的个数和类型,它特别适合用来实现多值返回。在 JavaScript 中并没有元组的概念,作为一门动态类型语言,它的优势是天然支持多类型元素数组。
let arr: [string, number][] = [
["张三", 13],
["李四", 14],
["王五", 15]
];
如果每个数组项不是数组,而是对象,那么写法如下:
let arr: {name: string, age: number}[] = [
{name: "刘备", age: 21},
{name: "关羽", age: 21},
{name: "张飞", age: 21}
]
4、任意类型any
any 指的是一个任意类型,它是官方提供的绕过静态类型检测的方法。如:
let arr: any[] = [111, "你好世界"]
注意:
非必要不使用any,这几乎违背了TS的出发点。
5、不确定变量unknown
unknown 是 TypeScript 3.0 中添加的一个类型,它主要用来描述类型并不确定的变量。在 3.0 以前的版本中,只有使用 any 才能满足这种动态类型场景。与 any 不同的是,unknown 在类型上更安全。比如我们可以将任意类型的值赋值给 unknown,但 unknown 类型的值只能赋值给 unknown 或 any。
let str: unknown;
let num: string = str; // 不能将类型“unknown”分配给类型“string”。
let abc: any = str; // 没有报错
6、无返回值void
当一个函数没有返回值时,需要加上void:
function fn(one: number, two: number): void{
console.log(123)
}
fn(1,2);
7、undefined与null
这两个比较简单,此处省略。
8、never
never 表示永远不会发生值的类型。一个永远不会有返回值,或者产生死循环的函数,就可以加上never:
// 只有产生报错才会产生错误返回
function fn1(str: string): never {
throw Error(str);
}
// 只有条件为真才会产生值返回
function fn2(): never {
while(true) {}
}
9、object
object 类型表示非原始类型的类型,即非 number、string、boolean、bigint、symbol、null、undefined 的类型。
10、类型断言
如果一段js代码,你已经可以很明确的知道返回值一定是某种数据类型,就可以使用as给它断言:
const arr: number[] = [1,2,3,4]
const result: number = arr.find(num=>num>2) as number;
五、字面量类型
在 TypeScript 中,字面量不仅可以表示值,还可以表示类型,即所谓的字面量类型。
使用值所代表的数据类型来作为变量的数据类型,简单来说,即:值也可以作为类型使用。但要注意,目前只能是string、number和boolean三种数据类型可以写成字面量类型。
const str: "你好世界" = "你好世界";
const num: 123 = 123;
const bool: true = true;
六、返回值类型
在上文讲述void的时候,其实已经使用过了,大致如下:
function fn(one: number, two: number): number{
return one + two;
}
fn(1,2);
七、剩余参数
在 ES6 中,JavaScript 支持函数参数的剩余参数,它可以把多个参数收集到一个变量中。同样,在TypeScript 中也支持这样的参数类型定义。
// 参数个数不确定,但要实现累加
function fn(num1: number, ...nums: number[]): number{
return nums.reduce((prev,next) => prev + next, num1);
}
console.log( fn(1,2) );
console.log( fn(1,2,3) );
效果如图:
八、this
原生JS中的this指向非常模糊,函数中的this只有当函数被调用了才能知道this指向谁。而TS中,严格模式下必须显式地指定this指向,否则如下图所示:
因此代码应该改为:
function fn(this: Window, str: string){ // 这里Window是大写
console.log(this);
}
window.fn = fn; // 这里window是小写
window.fn("你好世界");
这里要注意:
1、这段代码不会成功执行,因为你是在ts-node环境下运行,不存在window,也不会有global;
2、这里的this是伪形参,不会被编译为js。