• 8.typescript-函数的类型


    今儿个甚是乏累呢~

    但是

    <----------------------------------------------------------------------下面可能是正题儿---------------------------------------------------------------------->

    1.函数声明

    1 function student(x:string,y:number):string{
    2     return `我是${x},今年${y}岁`;
    3 }
    4 
    5 console.log(student("wzy",22));  // 我是wzy,今年22岁

    形式和JavaScript中的函数声明一样,不一样的是什么呢?

    (1)指定了参数的类型(因为有类型检查,所以要遵循),随后指定了返回值的类型,

    这个时候返回值类型可以省略,因为typescript会根据返回语句自动推断出返回值的类型。

    (2)参数不可多不可少,只能刚刚好,且和顺序有关。

    1 function student(x:string,y:number){
    2     console.log(`我是${x},今年${y}岁`);
    3 }
    4 
    5 student(22,"wzy"); 
    6 //  Argument of type '22' is not assignable to parameter of type 'string'.

    2.函数表达式

    有些话总是需要照抄下来的,比如下面这两句话

    如果要我们现在写一个对函数表达式(Function Expression)的定义,可能会写成这样:

    1 let student = function(x:string,y:number):string{
    2     return `我是${x},今年${y}岁`;
    3 }
    4 
    5 console.log(student("wzy",22));  // 我是wzy,今年22岁

    这是可以通过编译的,不过事实上,上面的代码只对等号右侧的匿名函数进行了类型定义,而等号左边的 student,是通过赋值操作进行类型推论而推断出来的。

    如果需要我们手动给 student 添加类型,则应该是这样:

    1 let student:(x:string,y:number)=>string = function(x:string,y:number):string{
    2     return `我是${x},今年${y}岁`;
    3 }
    4 
    5 console.log(student("wzy",22)); // 我是wzy,今年22岁

    这是就需要多谈两句了:

    (1)前后参数名称可以不一致

     1 let student:(x:string,y:number)=>string = function(name:string,age:number):string{
     2     return `我是${x},今年${y}岁`;
     3 }
     4 // 这样对吗?嗯!好像是哪里不太对~
     5 // Cannot find name 'x'.   
     6 // Cannot find name 'y'.
     7 
     8 let student:(x:string,y:number)=>string = function(name:string,age:number):string{
     9     return `我是${name},今年${age}岁`;
    10 }
    11 // 这样就对了~

    (2)我对这种声明函数的方式的理解就是:

    let student : (x:string,y:number)=>string = function(name:string,age:number):string{}
    声明变量 指定函数类型 根据指定函数类型定义函数

    此时再根据之前讲过的“类型推论”,就有以下这样的声明方式了
    1 let student:(x:string,y:number)=>string = function(name,age){
    2     return `我是${name},今年${age}岁`;
    3 }
    4 5 let student = function(name:string,age:number):string{
    6     return `我是${name},今年${age}岁`;
    7 }
    
    

    据说这叫“按上下文归类”,是类型推论的一种。

    (3)之前我们也讲过,当没有返回值的时候要怎样,在这种完整的函数声明的情况下是不可以返回值为空的,这时我们就会想起void

     1 let student:(x:string,y:number) = function(name,age){  
     2     console.log(`我是${name},今年${age}岁`);
     3 }
     4 
     5 //  '=>' expected.
     6 // 这样是不允许的,也不要妄想   =>""  这样,人家就没有""这种类型好吗
     7 
     8 let student:(x:string,y:number)=>void = function(name,age){  
     9     console.log(`我是${name},今年${age}岁`);
    10 }
    11 // 还是老老实实的这样子吧

    3.接口中函数的定义

    1 interface Student{
    2     (x:string,y:number):string
    3 }
    4 
    5 let str1:Student;
    6 str1 = function(x,y){
    7     return `我是${x},今年${y}岁`; 
    8 }

    4.可选参数

    之前提到过函数的参数是不可多不可少的,但是也可以像接口那样的形式用?表示可选参数

     1 function student(name:string,age:number,sex?:boolean){
     2     if(sex){
     3         return `name:${name},age:${age},sex:女`;
     4     }else{
     5         return `name:${name},age:${age},sex:未知`;
     6     }
     7 }
     8   
     9 console.log(student("weizeyang",22,true));   // name:weizeyang,age:22,sex:女
    10 console.log(student("weizeyang",22));        // name:weizeyang,age:22,sex:未知

    再看看它要注意哪些:

    (1)可选参数要放在必需参数后面

    (2)肚子好疼,不开心

      

    5.默认参数

    在typescript中,可以为函数中的参数设置一个默认值,当用户没有传这个参数或者传的值是undefined时,就显示默认值。

     1 function student(name:string,age:number,sex="女"){
     2     return `name:${name},age:${age},sex:${sex}`;
     3 }
     4   
     5 console.log(student("weizeyang",22,"未知"));  
     6 // name:weizeyang,age:22,sex:未知
     7 
     8 console.log(student("weizeyang",22));   
     9 // name:weizeyang,age:22,sex:女
    10 
    11 console.log(student("weizeyang",22,undefined));   
    12 // name:weizeyang,age:22,sex:女

    千古不无的注意点:

    (1)可以看到,默认值的参数识别为可选参数,但不必在必需参数后面。

    (2)虽说它是可选参数了耶不必放在必需参数后面了,但是一旦放在必需参数前面,就要明确写上undefined或者值,即不能空这。

    这样一来,写在前面也就不算是可选参数了。

     1 function student(sex="女",name:string,age:number){
     2     return `name:${name},age:${age},sex:${sex}`;
     3 }
     4   
     5 console.log(student("未知","weizeyang",22));  
     6 // name:weizeyang,age:22,sex:未知
     7 
     8 console.log(student("weizeyang",22));   
     9 // Expected 3 arguments, but got 2.
    10 
    11 console.log(student(undefined,"weizeyang",22));   
    12 // name:weizeyang,age:22,sex:女

    不知道别人看得懂这句话不,反正我是看懂说的是啥了。

    6.剩余参数

     之前讲过的必要参数、默认参数和可选参数表示的都是某一个参数,有时,你想同时操作多个参数,或者你并不知道会有多少个参数会传进来。

    在JavaScript中,你可以使用arguments来访问所有传入的参数。

    在typescript里,你可以把所有参数收集到一个变量里:

    1 function student(age:number,sex:boolean,...name:string[]){
    2     return `我是${name.join("")},年龄${age}`;
    3 } 
    4 
    5 console.log(student(22,true,"wei","ze","yang"));
    6 // 我是weizeyang,年龄22

    来吧,注意点:

    (1)剩余参数会被当做个数不限的可选参数,可以一个都没有,也可以有任意个。同样要放在必要参数后面。

    (2)是数组类型,名字是省略号后面的字段名,可以在函数体内使用这个数组。

    (3)当调用函数时,别传入数组,依次传入就行。

    7.Lambda表达式和使用this

    在JavaScript里,this的值在函数被调用的时候才会指定。学过JavaScript的都知道this很是让人头疼啊!

     1 var student = {
     2     names: ["wzy", "wyy", "wxy", "yz"],
     3     getName: function() {
     4         
     5         return function(){
     6             var item = Math.floor(Math.random() * 4);
     7             console.log(this);  
     8 
     9             return {
    10                 name: this.names[item]    //  Cannot read property 'names' of undefined
    11             }
    12         }
    13     }
    14 }
    15 
    16 let sname = student.getName();
    17 console.log("my name is " + sname().name);

    7行打印出的是window,因为这里没有对this进行动态绑定

     1 "use strict";   // 严格模式
     2 
     3 var student = {
     4     names: ["wzy", "wyy", "wxy", "yz"],
     5     getName: function() {
     6         
     7         return function(){
     8             var item = Math.floor(Math.random() * 4);
     9             console.log(this);    // undefined
    10 
    11             return {
    12                 name: this.names[item]    //  Cannot read property 'names' of undefined
    13             }
    14         }
    15     }
    16 }
    17 
    18 let sname = student.getName();
    19 console.log("my name is " + sname().name);

    9行打印出的是undefined,看着和上面的好像也没什么差别,实则现在是在JavaScript严格模式下(咱们一直都在),打印出的就是undefined了。

    为了解决这个问题,我们可以在函数被返回时就绑好正确的this。 这样的话,无论之后怎么使用它,都会引用绑定的‘student’对象。

    我们把函数表达式变为使用lambda表达式( () => {} )。 这样就会在函数创建的时候就指定了‘this’值,而不是在函数调用的时候。

     1 var student = {
     2     names: ["wzy", "wyy", "wxy", "yz"],
     3     getName: function() {
     4         console.log(this);
     5         // 注意:下面这行是一个lambda,允许我们提前捕捉它
     6         return () => {
     7             var item = Math.floor(Math.random() * 4);
     8             console.log(this);
     9             
    10             return {
    11                 name: this.names[item]
    12             }
    13         }
    14     }
    15 }
    16 
    17 let sname = student.getName();
    18 console.log("my name is " + sname().name);

    在第4,8行打印出了

    即student这个对象,大功告成

    8.重载

     举个栗子:

     1 function schools(type:number|string):number|string{
     2     if(typeof type === "number"){
     3         return type.toFixed(2);
     4     }else if(typeof type === "string"){
     5         return type.substring(0,1);
     6     }
     7 }
     8 
     9 console.log(schools(1));       // 1.00
    10 console.log(schools("wzy"));   // w

    上面函数的参数和返回值的类型均使用了联合类型的形式,这样一来我们就不能准确的表达我传入的是number类型的返回的就要是number类型得了

    这时就要引入重载的概念了

    在学Java的时候,重载是这样讲的:函数名相同,函数的参数列表不同(包括参数个数和参数类型),返回值类型可同可不同

    网上的例子是这样给出的:

     1 function schools(type:number):number;
     2 function schools(type:string):string;
     3 function schools(type:number|string):number|string{
     4     if(typeof type === "number"){
     5         return type.toFixed(2);
     6     }else if(typeof type === "string"){
     7         return type.substring(0,1);
     8     }
     9 }
    10 
    11 console.log(schools(1));       // 1.00
    12 console.log(schools("wzy"));   // w

    就是讲这两个函数在上面多声明了几次

    需要注意的是:

    (1)TypeScript 会优先从最前面的函数定义开始匹配,所以多个函数定义如果有包含关系,需要优先把精确的定义写在前面。

    再给个栗子:

     1 function schools(type:number):number;
     2 function schools(type:string):string;
     3 function schools(type:number | string | boolean):number | string | boolean{
     4     if(typeof type === "number"){
     5         return type.toFixed(2);
     6     }else if(typeof type === "string"){
     7         return type.substring(0,1);
     8     }else if(typeof type === "boolean"){
     9         return true;
    10     }
    11 }
    12 
    13 console.log(schools(1));       // 1.00
    14 console.log(schools("wzy"));   // w
    15 console.log(schools(true));    
    16 //  Argument of type 'true' is not assignable to parameter of type 'string'.

    (2)说明3行的代码并不属于重载部分,这里只有1,2行的函数重载起作用。用除这两种外的其他类型的参数调用schools会产生错误。

    (3)1,2行是定义了两个函数,而3行只是对这两个重载函数的实现。

    我在知乎上看到的总结是这样说的,因为会有好多人觉得typescript的重载存在的意义不大:

      TypeScript 的重载是为了给调用者看,方便调用者知道该怎么调用(同时 tsc 也会进行静态检查以避免错误的调用)。

      有助于IDE的代码提示,以及返回值的类型约束。

    <----------------------------------------------------------------------上面可能是正题儿---------------------------------------------------------------------->

  • 相关阅读:
    MySQL数据库安装和基本使用
    Android studio JNI技术实现与本地C++链接
    笔记 java中i++ 和 ++i的区别
    LaTeX中添加usepackage{subfigure}一直报错的解决办法,亲测
    Android Studio 出现“Cannot resolve symbol” 解决办法
    记录一个sql
    linux 文件内容查找、去重、统计
    MVC框架的模板缓存
    Linux 命令学习
    笔记 :PHP中的数据结构库SPL
  • 原文地址:https://www.cnblogs.com/wzy1569178479/p/7364340.html
Copyright © 2020-2023  润新知