函数详解

函数的标注

一个函数的标注包括函数参数的标注以及函数返回值的标注

  1. function fn(a:string):string{};// 直接标注
  2. let fn:(a:string)=>string=function(a){} //声明式标注
  3. type callback=(a:string):string; //类型别名方式标注
  4. interface ICallBack{ //接口方式标注
  5. (a:string):string;
  6. }
  7. let fn:callback=function(a){};
  8. let fn:ICallBack=function(a){};

可选参数和默认参数

可选参数

通过函数名后面添加?来标注该参数是可选的

  1. let div = document.querySelector('div');
  2. function css(el: HTMLElement, attr: string, val?: any) {
  3. }
  4. div && css( div, 'width', '100px' ); // 设置
  5. div && css( div, 'width' ); // 获取

默认参数

我们还可以给参数设置默认值

  • 有默认值的参数是可选的
  • 设置了默认值的参数是可以根据值自动推导类型
  1. function sort(items: Array<number>, order = 'desc') {}
  2. sort([1,2,3]);
  3. // 也可以通过联合类型来限制取值
  4. function sort(items: Array<number>, order:'desc'|'asc' = 'desc') {} // ok
  5. sort([1,2,3]);
  6. sort([1,2,3], 'asc');// ok
  7. sort([1,2,3], 'abc');// error

剩余参数

剩余参数是一个数组所以标注的时候一定要小心

  1. interface Iobj{
  2. [key:string]:any
  3. }
  4. function merge(target:Iobj,...others:Array<Iobj>){
  5. return others.reduce((prev,current){
  6. prev=Object.assign(prev,current);
  7. return prev
  8. },target)
  9. }
  10. let newObj = merge({x: 1}, {y: 2}, {z: 3});

函数中的this

无论是javascript还是typescript,函数中的this都是我们需要关心的,那函数中的this的类型该如何标注呢

普通函数

对于普通函数而言,this是会随着调用环境的变化而变化的,所以默认情况下,普通函数中的this被标注为any,但我们可以在函数的第一个参数位(它不占据世纪参数位置)上显示的标注this的类型

  1. interface T {
  2. a:number
  3. fn:(x:number)=>void;
  4. }
  5. let obj:T ={
  6. a:1,
  7. fn(x:number){
  8. console.log(this)
  9. }
  10. }
  11. let obj2 :T={
  12. a:1,
  13. fn(this:T,x:number){
  14. //通过第一个参数位标注 this 的类型,它对实际参数不会有影响
  15. console.log(this)
  16. }
  17. }
  18. obj2.fn(1);

箭头函数

箭头函数的this不能像普通函数那样进行标注,他的this标注取决于它所在的作用域this的标注类型

  1. interface T {
  2. a:number ;
  3. fn:(x:number)=>void;
  4. }
  5. let obj2:T={
  6. a:2,
  7. fn(this:T){
  8. return ()=>{
  9. console.log(this)
  10. }

函数重载

有的时候,同一个函数会接收不同类型的返回值,我们可以使用函数重载来实现

  1. function showOrHide(ele:HTMLElement,attr:string,value:"block"|"none"|number){
  2. //
  3. }
  4. let div=document.queryselector("div");
  5. if(div){
  6. showOrHide(div,"display","none");//这样是符合标准的
  7. showOrHide(div,"opacticy",1); //这样也行
  8. //但是会出现这么一种情况就是
  9. showOrHide(div,"display",1) //这样也是可以的但是这样明显是错误的
  10. // error,这里是有问题的,虽然通过联合类型能够处理同时接收不同类型的参数,但是多个参数之 间是一种组合的模式,我们需要的应该是一种对应的关系
  11. }

函数重载写法

  1. function showOrHide(ele:HTMLElement,attr:'display',value:'block'|'none);
  2. function showOrHide(ele:HTMLElement,attr:'opacity',value:number);
  3. function showOrHide(ele:HTMLElement,attr:string,value:any){
  4. ele.style[attr]=value
  5. }
  6. let div=document.querySelector('div');
  7. if(div){
  8. showOrHide(div,'display','none');
  9. showOrHide(div,'opacity',1);
  10. showOrHide(div,'display',1);//这个时候类型系统就会检查到错误并且提醒用户
  11. }

重载函数类型只需要定义结构,不需要实体,类似接口

  1. interface PlainObject{
  2. [key:string]:string |number
  3. }
  4. function css(ele:HTMLElement,attr:PlainObject);
  5. function css(ele:HTMLElement,attr:string,value:string|number);
  6. function css(ele:HTMLElement,attr:any,value?:any){
  7. if(typeof attr==='string' && value){
  8. ele.style[attr]=value;
  9. }
  10. if (typeof attr==='object'){
  11. for (let key in attr){
  12. ele.style[attr]=attr[key]
  13. }
  14. }
  15. }
  16. let div =document.queryselector('div');
  17. if(div){
  18. css(div,'width','100px');
  19. css(div,{
  20. width:"100px"
  21. });
  22. css(div,"width") //这里没在函数重载里面定义相关的逻辑,就会检查出问题
  23. }