# 函数类型

# 显式指定类型

// 显式指定函数参数和返回值的类型
const fn = (a: number, b: number): number => {
  return a + b;
};
console.log(fn(1, 2));	// 3
/*
function 函数名(参数:参数类型):返回值的类型{
	return 返回值
}
函数特殊 , 如果一个函数没有return 这个函数返回值类型是 void
*/

# 类型别名

// (参数:类型)=>返回值类型 
type FnType = (a: number, b: number) => number;

let fn: FnType = (a, b) => {
  return a + b;
};
console.log(fn(1, 2));	// 3

// 当函数作为对象的属性时
type ObjType = { 
  fn: (str: string) => number 
};

let obj: ObjType = {
  fn: (str) => {
    return 1;
  },
};
console.log(obj.fn(""));	// 1

# 接口

//接口指定 函数类型 
interface FnItf {
  //(参数:类型):返回值类型
  (name: string): string;
}

let fn: FnItf = (name: string) => {
  return "我叫" + name;
};

console.log(fn("小苏同学"));	// 我叫小苏同学

// 当函数作为对象的属性时
interface FnItf {
  (str: string): number;
}
interface ObjItf {
  fn: FnItf;
}
let obj: ObjItf = {
  fn: (str) => {
    return 1;
  },
};
console.log(obj.fn("小苏同学"));	// 1

# 参数类型

# 默认参数

在函数调用时,若传参了就优先使用传的,若未传参就使用默认值。

function fn(a: number, b: number = 5): number {
  return a + b;
}
console.log(fn(1, 2)); // 3
console.log(fn(3)); // 8

函数的默认参数类型必须是参数类型的子类型

function fn(x: number | string = "hello") {
  console.log(x);
}
fn();	// hello
fn(1);	// 1
fn("su");	// su

这里x参数的类型就是联合类型number | string,函数默认参数的类型就是联合类型的子类型

# 缺省参数

在类型标注的:前添加?表示 log 函数的参数 x 就是可缺省的;

function fn(msg?: string): void {
  console.log(msg);
}
fn();	// undefined
fn("su");	// su

可缺省是不是相当于msg参数的类型就是和string | undefined等价呢?

这个当然不是,string | undefined的意思是这两个类型中的一种,而可缺省是不传的意思。

# 剩余参数

...nums就是数组

function fn(...nums: number[]) {
  return nums.reduce((a, b) => a + b, 0);
}
console.log(fn(1, 2)); // 3
console.log(fn(1, 2, 3)); // 6
console.log(fn()); // 0

# this

函数中的this问题,一直都是javascript最令人头疼的问题,因为this的指向只有函数调用的时候才能确定。还有一些可以改变this指向的方法(applycallbind)。

但是在Typescript中,必须要明确的指定this的类型(严格模式下)。

在函数的第一个形参的位置注明

ts提供了Window类型,window就是这个Window类型的对象。

export {}
function person(this: Window, name: string):void {
  	//Window类型中没有myname这个属性,所以需要自己扩展这个属性
    this.myname = name;
    console.log(this.myname);
}
// 加了export {}后person就不是window下的属性了,需要我们赋到window.person上
window.person = person;
window.person('小苏同学');

单单是上面的代码是有问题的,我们还需要创建一个类型声明文件global.d.ts,为window对象上扩展两个属性person、myname;

interface Window {
  person: (n: string) => void;
  myname: string;
}

定义对象的函数属性时,只要实际调用中 this 的指向与指定的 this 指向不同,TypeScript 就能发现 this 指向的错误

interface ObjType {
  name: string;
  say: (this: ObjType) => void;
}

let obj: ObjType = {
  name: "小苏同学",
  say() {
    console.log(this.name);
  },
};

obj.say(); // 小苏同学

let talk = obj.say;
talk();	// 报错

注意:

1. 显式声明函数的返回值类型为 undfined,则会出现错误提示,如果没有返回值,我们用void表示;
2. 注意:显式注解函数中的 this 类型,它表面上占据了第一个形参的位置,但并不意味着函数真的多了一个参数,因为 TypeScript 转译为 JavaScript 后,“伪形参” this 会被抹掉,这算是 TypeScript 为数不多的特有语法。