第三节:TypeScript类型补充和函数详解(参数、返回值、类型、参数【可选/默认】、剩余参数、this、重载)
一. TypeScript类型补充
1. 类型断言
有时候TypeScript无法获取具体的类型信息,这个我们需要使用类型断言(Type Assertions) ,TypeScript只允许类型断言转换为 更具体 或者 不太具体 的类型版本,此规则可防止不可能的强制转换。
符号:as
// 1.类型断言 as const el = document.getElementById("why") as HTMLImageElement el.src = "url地址" // 2.另外案例: Person是Student的父类 class Person { } class Student extends Person { studying() { } } function sayHello(p: Person) { (p as Student).studying() } const stu = new Student() sayHello(stu)
2. 非空断言
我们确定传入的参数是有值的,这个时候我们可以使用非空类型断言。非空断言使用的是 ! ,表示可以确定某个标识符是有值的,跳过ts在编译阶段对它的检测
符号:!
// message? -> undefined | string function printMessageLength(message?: string) { // if (message) { // console.log(message.length) // } // vue3源码中很多这种写法 console.log(message!.length) } printMessageLength("aaaa") printMessageLength("hello world")
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?.name) console.log(info.friend?.age) console.log(info.friend?.girlFriend?.name)
4. !!运算符
将一个其他类型转换成boolean类型;类似于Boolean(变量)的方式;
const message = "Hello World" // const flag = Boolean(message) // console.log(flag) const flag = !!message console.log(flag)
5. ??运算符
它是ES11增加的新特性;
空值合并操作符(??)是一个逻辑操作符,当操作符的左侧是 null 或者 undefined 时,返回其右侧操作数,否则返回左侧操作数 。
let msg1: string | null = 'hello ts'; let msg2: string | null = null; const result1 = msg1 ?? 'hello js'; // 上面等价于 const result2 = msg1 ? msg1 : 'hello js'; console.log(result1); console.log(result2); const result3 = msg2 ?? 'hello js'; // 上面等价于 const result4 = msg2 ? msg2 : 'hello js'; console.log(result3); console.log(result4);
6. 字面量
// 1. 如下,这里声明的字面量类型为 'hello ts' let msg1: 'hello ts' = 'hello ts'; // msg1='hhh'; //报错,类型错误,因为这里的类型是hello ts //2. 字面量类型的意义, 就是必须结合联合类型 type Alignment = 'left' | 'right' | 'center' let align: Alignment = 'left' align = 'right' align = 'center'
7. 类型缩小
在给定的执行路径中,我们可以缩小比声明时更小的类型,这个过程称之为 缩小;
常见的类型保护有如下几种:
A. typeof
B. 平等缩小(比如===、!==)
C. instanceof (检查一个值是否是另一个值的“实例” )
D. in
// 1.typeof的类型缩小 type IDType = number | string function printID(id: IDType) { if (typeof id === 'string') { console.log(id.toUpperCase()) } else { console.log(id) } } // 2.平等的类型缩小(=== == !== !=/switch) type Direction = "left" | "right" | "top" | "bottom" function printDirection(direction: Direction) { // 1.if判断 // if (direction === 'left') { // console.log(direction) // } else if () // 2.switch判断 // switch (direction) { // case 'left': // console.log(direction) // break; // case ... // } } // 3.instanceof 检查一个值是否是另一个值的“实例” function printTime(time: string | Date) { if (time instanceof Date) { console.log(time.toUTCString()) } else { console.log(time) } } class Student { studying() { } } class Teacher { teaching() { } } function work(p: Student | Teacher) { if (p instanceof Student) { p.studying() } else { p.teaching() } } const stu = new Student() work(stu) // 4. in(用于确定对象是否具有带名称的属性:in运算符,如果指定的属性在指定的对象或其原型链中,则in 运算符返回true;) type Fish = { swimming: () => void } type Dog = { running: () => void } function walk(animal: Fish | Dog) { if ('swimming' in animal) { animal.swimming() } else { animal.running() } } const fish: Fish = { swimming() { console.log("swimming") } } walk(fish)
二. TypeScript函数详解
1. 函数自身 参数类型 和 返回值类型
// 1. 函数的参数类型 function sum1(num1: number, num2: number) { return num1 + num2; } // 2. 函数的返回值类型 // 添加返回值的类型注解,这个注解出现在函数列表的后面: function sum2(num1: number, num2: number): number { return num1 + num2; } // 和变量的类型注解一样,我们通常情况下不需要返回类型注解,因为TypeScript会根据 return 返回值推断函数的返回类型: function sum3(num1: number, num2: number) { return num1 + num2; }
2. 作为参数的函数类型
可以编写函数类型的表达式(Function Type Expressions),来表示函数类型;
格式为: (n:xx,m:xx)=>xxx, 括号里的是参数名和参数类型,=>后面的是返回值类型,比如: (num1: number, num2: number) => void,代表的就是一个函数类型:
A. 接收两个参数的函数:num1和num2,并且都是number类型;
B. 并且这个函数是没有返回值的,所以是void;
// 案例1-函数作为参数进行传递 function calc(m1: number, m2: number, fn: (num1: number, num2: number) => number) { return fn(m1, m2); } const result1 = calc(10, 20, function (m, n) { return m - n; }) console.log(result1); const result2 = calc(10, 20, function (m, n) { return m * n; }); console.log(result2); // 案例2--定义常量时, 编写函数的类型 type myAddFnType = (num1: number, num2: number) => number; const Add1: myAddFnType = (m, n) => { return m + n; } console.log(Add1(10, 20));
3. 参数可选类型
符号:?
可选类型需要在必传参数的后面
function foo(x: number, y?: number) { if (y) { console.log(x+y); } else { console.log(x); } } foo(20, 30) foo(20)
4. 参数默认值
从ES6开始,JavaScript是支持默认参数的,TypeScript也是支持默认参数的:
格式: 直接 = 号 ,写上默认值就行了
//通常我们写的顺序: 必传参数 - 有默认值的参数 - 可选参数 function foo(y: number, x: number = 20, z?:number) { console.log(x, y) } foo(30)
5. 剩余参数
/* @totalNum: 默认初始值 @nums:数组 */ function sum(totalNum: number, ...nums: number[]) { let total = totalNum; for (const num of nums) { total += num; } return total; } console.log(sum(10,100)) console.log(sum(10,100,200)) console.log(sum(10,100,200,300))
6. this的默认推导
// this是可以被推导出来 info对象(TypeScript推导出来) const info = { name: "ypf", eating() { console.log(this.name + " is eating") } } info.eating()
7. this的不明确类型
type ThisType = { name: string }; function eating(this: ThisType, message: string) { console.log(this.name + " eating", message); } const info = { name: "why", eating: eating, }; // 隐式绑定 info.eating("哈哈哈"); // 显示绑定 eating.call({name: "kobe"}, "呵呵呵") eating.apply({name: "james"}, ["嘿嘿嘿"])
8. 函数重载
function add(num1: number, num2: number): number; // 没函数体 function add(num1: string, num2: string): string; function add(num1: any, num2: any): any { if (typeof num1 === 'string' && typeof num2 === 'string') { return num1.length + num2.length } return num1 + num2 } const result1 = add(20, 30) const result2 = add("abc", "cba") console.log(result1) console.log(result2) // 在函数的重载中, 实现函数是不能直接被调用的 // add({name: "why"}, {age: 18}) // 实现方式二: 函数的重载 function getLength(args: string): number; function getLength(args: any[]): number; function getLength(args: any): number { return args.length } console.log(getLength("abc")) console.log(getLength([123, 321, 123]))
!
- 作 者 : Yaopengfei(姚鹏飞)
- 博客地址 : http://www.cnblogs.com/yaopengfei/
- 声 明1 : 如有错误,欢迎讨论,请勿谩骂^_^。
- 声 明2 : 原创博客请在转载时保留原文链接或在文章开头加上本人博客地址,否则保留追究法律责任的权利。