函数类型

在javascript开发中,函数是重要的组成部门,并且可以作为一等公民(例如函数可以作为参数,也可以作为返回值进行传递等),在使用函数的过程中,可以编写函数类型的表达式来表示函数类型

export function useInterval(callback: () => void, delay: number | undefined, options?: { immediate?: boolean }): any {
    const immediate = options?.immediate;

    const fnRef = useLatest(callback);

    const tick = useRef(undefined);

    useEffect(() => {
        // 如果有更变的话删除之前的定时器
        clearInterval(tick.current?._id);
        if (typeof delay !== 'number' || delay < 0) {
            return;
        }
        if (immediate) {
            fnRef.current();
        }
        tick.current = setInterval(() => {
            fnRef.current();
        }, delay);
        return () => {
            clearInterval(tick.current?._id);
        };
        // eslint-disable-next-line
    }, [delay]);
}

上面的代码中,我实现了一个用于创建和管理一个定时器功能的函数

callback:定时器触发时要执行的回调函数.

delay number或undefined类型,定时器的时间间隔

if (typeof delay !== 'number' || delay < 0) { return; } 如果delay设置为undefined或小于0,定时器将不会启动.

options: 可选参数,包含一个可选的immediate属性


函数参数的类型

可选参数

函数不仅可以接受参数,而且可以指定某些参数是可选的,也拿上面的示例,options为可选参数,可以接收{}或undefined类型的数据,如果没有向options传递数据,那么options的值就为undefined

注意,在函数参数列表中,可选类型参数必须放在必选类型参数的后面.

默认参数

从es6开始,javascript和typescript都支持默认参数

function foo(x: number, y: number =20 ) {console.log(x, y)}
foo(30)
export {}

可以看到参数y有一个默认值20,因此y的类型实际上是undefined和number类型的联合

  • 如果向y传入了值,则使用传入的值
  • 如果向y传入undefined或没有传入值,则使用默认值20

注意:在函数参数中,参数的顺序应该是先写必传参数,然后写有默认值的参数,最后写可选参数.


剩余参数

从es6开始,javascript也开始支持剩余参数,剩余参数语法允许我们将不定数量的参数放到一个数组中

function sum(initalNum: number, ...nums: number[]): number{
    let total: number = initalNum
    for (const num of nums) { total += num }
    return total
}
console.log(sum(1, 2, 3, 4))

可以看到...nums就是剩余参数,当调用sum函数时,除了第一个参数,其他的参数都会传递给nums


this的类型

javascript中的this是一个比较难理解的概念,简单来说,this表示当前函数的执行上下文,但是在不同的情况下,它所绑定的值是不同的

  • 在一个对象中使用this时,它会绑定到该对象上
  • 在全局环境中使用this时,它会绑定到全局对象上
class Code {
    // success
    static SUCCESS = 0
    // 默认code
    static FAILED = -1
    // 当ErrorCode不存在ERROR_CODE_MAPPING常量,会报这个错误
    static DEFAULT_ATTRIBUTE_CODE = -2
    // 无效的SIGN参数
    static INVALID_SIGN = -4
    // 超时
    static TIMEOUT = -5

    // 为 Code 类添加一个索引签名
    static [key: string]: number;
}

export class Message {
    maps: { [key: number]: string | null } = {};
     // 通用
     SUCCESS = 'success!';
     FAILED = '未知的code码,请检查响应代码';
     INVALID_SIGN = '无效的标识';
     TIMEOUT = '访问超时';

    constructor() {
        const keys = Object.keys(Code) as string[]; // 类型断言为 string[]
        for (const key of keys) {
            const code = (Code as any)[key]; // 使用类型断言绕过类型检查
            if (this.hasOwnProperty(key)) {
                this.maps[code] = (this as any)[key]; // 使用类型断言绕过类型检查
            }else {
                this.maps[code] = null;
            }
        }
    }
}
const message = new Message();
console.log(message.maps);

TypeScript-ts的函数类型详解_typescript

这里我们在Message构造函数中使用this关键字引用了当前实例对象Message,并将Code的属性和Message实例属性的值存储到Message实例中maps属性对象里


函数重载

在编写javascript函数时,如果函数名称相同但参数的数量或类型不同,则被称其为函数重载

// 1.函数重载,使用联合类型实现
function add(a1: number | string, a2: number | string) {
    if (typeof a1 === "number" && typeof a2 === "number") { // 类型缩小
        return a1 + a2
    }else if (typeof a1 === "string" && typeof a2 === "string"){
        return a1 + a2
    }
}
// 2.调用add函数,可以使字符串和数字类型相加
console.log(add(10 ,20))
console.log(add('coder', 'why'))

// 在typescript中,为了实现函数重载,还可以编写不同的重载签名表示函数可以以不同的方式进行调用
function sum(a1: number, a2: number): number
function sum(a1: string, a2: string): string
// 通用函数体
function sum (a1: any, a2: any): any {
    return a1 + a2
}
// 调用sum函数,可以使字符串和数字类型相加
console.log(sum(20 , 30))
console.log(sum("coder", "why"))
export {}