zoukankan      html  css  js  c++  java
  • 第三节: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)
    View Code

    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)
    View Code

    二. 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. 剩余参数

     从ES6开始,JavaScript也支持剩余参数,剩余参数语法允许我们将一个不定数量的参数放到一个数组中。 ts也支持
    /* 
        @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 : 原创博客请在转载时保留原文链接或在文章开头加上本人博客地址,否则保留追究法律责任的权利。
     
  • 相关阅读:
    apply()和call()的区别
    强制类型转换
    浮动理解
    清除浮动的方式
    五大主流浏览器及四大内核
    CSS引入方式
    js构建类的方法
    web前端与后端的理解区分
    Java的API及Object
    面向对象之this关键字
  • 原文地址:https://www.cnblogs.com/yaopengfei/p/15503588.html
Copyright © 2011-2022 走看看