函数

130 阅读5分钟

简介

函数的类型声明

和JS相比增加了参数类型和返回值类型,void标识表示没有任何返回

function hello(txt: string): void {
	console.log("hello " + txt);
}

如果函数没有返回值,不添加:void也会类型推断返回值为void

function hello2(txt: string) {
	console.log("hello " + txt);
}

变量函数赋值写法

// 写法一
const hello3 = function (txt: string) {
	console.log("hello " + txt);
};
// 写法二, 类型和参数名必须放在括号中,没有参数名txt 会推断string为any类型
const hello4: (txt: string) => void = function (txt) {
	console.log("hello " + txt);
};

type定义函数类型别名

type MyFunc = (txt:string) => void;
const hello5:MyFunc = function (txt) {
  console.log('hello ' + txt);
}

函数也可以用typeof 提取类型, myAdd和add类型相同,可以用typeof 提取add的函数类型

function add( x:number, y:number ) {
    return x + y;
}
const myAdd:typeof add = function (x, y) {
    return x + y;

函数参数

函数参数可以少写,允许参数不足,不能多写,

let myFunc: (a:number, b:number) => number;
myFunc = (a:number) => a; // 正确
myFunc(4) // 调用的时候需要传两个参数,一个会报错
myFunc = (a:number, b:number, c:number ) => a + b + c; // 报错

函数类型的对象写法

当函数本身存在属性时,可以使用该写法,使用较少

{
    (参数列表): 返回值
}
let add2:{
    (x:number, y:number):number,
    version: string
};
function addf (x: number, y: number) {
    return x + y;
};
addf.version = '5.0'
add2 = addf

函数具体分类及详情

Function 类型

Function就是函数类型,可表示任何函数,接收任意参数,没个参数都是any类型,返回值也是any,无任何约束,不建议使用

function doSomething(f:Function) {
    return f(1, 2, 3);
}

箭头函数

箭头函数就是普通函数的简化写法,和普通函数类似

const repeat = ( str:string, times:number ):string => str.repeat(times);

箭头函数参数,void写在箭头后面

function greet( fn:(a:string) => void ):void {
    fn('world');
}

带有返回类型的箭头函数

type Person1 = { name: string };
const people = ['alice', 'bob', 'jan'].map(
  (name):Person1 => ({ name })
);

可选参数

可以省略的参数, 可选参数只能放在参数列表中必选参数的后面

function f2(x?:number) { // x的类型等同于 number | undefined
    // ...
}
f2(); // OK
f2(10); // OK
f2(undefined) // OK 

参数默认值

与JS一致,不传入参数时取默认值, 有参数默认值可以省略不传,也可以省略类型声明,可以通过默认值进行类型推断 可选参数与默认值不能同时使用

function createPoint( x:number = 0, y:number = 0 ):[number, number] {
    return [x, y];
}
createPoint() // [0, 0]

参数解构

type ABC = { a:number; b:number; c:number };
function sum({ a, b, c }:ABC) {
  console.log(a + b + c);
}

rest 参数

函数剩余的所有参数,可以是数组或者元组

rest 参数为数组

function multiply(n:number, ...m:number[]) {
    return m.map((x) => n * x);
  }

rest 参数为元组, 可选参数后面加个?

function f3(...args:[boolean, number?]) {
    // ...
}

rest 参数解构

function repeat2(...[str, times]:[string, number] ):string {
    return str.repeat(times);
}
// 等同于如下
function repeat3( str: string, times: number ):string {
    return str.repeat(times);
}

只读参数

参数至刻度,不能更改,较少用

function arraySum( arr:readonly number[] ) {
    // ...
    arr[0] = 0; // 报错
}

void 类型

没有返回值的函数, 因为函数没有返回值默认是undefined,所以,void函数返回undefined可以

function f4():void {
    console.log('hello');
}
function f5():void {
    return undefined; // 正确
}
function f6():void {
    return null; // 严格模式下错误,非严格模式下可以返回null(strictNullChecks)
}

函数运行错误抛出异常,可以将返回值写成void

function throwErr():void {
    throw new Error('something wrong');
}

never 不会出现的值

函数出现异常或者陷入死循环,无法返回正常的值,返回值类型就是never

function fail(msg:string):never {
    throw new Error(msg);
}

const sing = function():never {
    while (true) {
        console.log('sing');
    }
};

返回错误并不是never

function failReturn():Error { 
    return new Error("Something failed");
}

函数仅在某些条件下抛出异常,返回值可以省略never nerve是TS的底层类型,所有类型都包含nerve

function sometimesThrow():number {
    if (Math.random() > 0.5) {
        return 100;
    }
    throw new Error('Something went wrong');
  }
const result = sometimesThrow();

高阶函数

函数的返回值是函数,那么前一个函数就是高阶函数

(someValue: number) => (multiplier: number) => someValue * multiplier;

类似的高阶组件也是相同概念,接受一个组件,返回一个组件

函数重载

函数可以接受不同类型或不同个数的参数,并根据参数的不同执行不同的函数行为,称之为函数重载

function makeDate(timestamp: number): Date
function makeDate(m: number, d: number, y: number): Date
function makeDate(mOrTimestamp: number, d?: number, y?: number): Date {
  if (d !== undefined && y !== undefined) {
    return new Date(y, mOrTimestamp, d)
  } else {
    return new Date(mOrTimestamp)
  }
}

const d1 = makeDate(12345678) // 正常
const d2 = makeDate(5, 6, 7) // 正常
const d3 = makeDate(5, 9) // 报错

如上,mackData函数,只能接受一个或者三个参数,不能接受两个参数,只能执行重载的的函数类型

函数重载参数可以使用字符串或者数组,但是不能使用可能存在的参数,因为TS只能使用一个函数解析重载

function len(s: string): number
function len(arr: any[]): number
function len(x: any) {
  return x.length
}
len('hello') // OK
len([1, 2, 3]) // OK 
len(Math.random() > 0.5 ? 'hello' : [4, 5, 6]) // 错误

重载是比较复杂的类型声明,如果可以,应优先使用联合类型替代函数重载,除非多个参数、或者某个参数与返回值存在对应关系

function len(x: any[] | string) {
   return x.length
}

构造函数

构造函数使用new关键字,类的本质也是构造函数

class Animal {
    numLegs:number = 4;
}
type AnimalConstructor = new () => Animal; // AnimalConstructor:构造函数
function create(c:AnimalConstructor):Animal {
    return new c();
}
const aa = create(Animal);

既可以是构造函数,也可以是普通函数的对象写法

type F = {
    new (s:string): object;
    (n?:number): number;
}