这里通过五个示例逐步理解泛型调用和函数调用签名
/*
* @Author: Zheng Lei
* @Email: baimoc@163.com
* @Date: 2023-01-18 16:29:21
* @LastEditTime: 2023-01-18 17:13:43
* @FilePath: \baimo_music\demo.ts
*/
// 一、--------------------------------------------------------
// () 内是函数参数类型约束
// : 后是函数返回值类型约束
interface IFnCall {
(name: string, age: number): string
}
// IFnCall 是函数调用签名
const foo: IFnCall = function (name, age) {
return name + age
}
// 函数调用
foo('tom', 10)
// --------------------------------------------------------
// 定义第一个参数为一个函数,并且该函数返回值的类型为 string
interface IFnCall2 {
(fn: () => string, age: number): string
}
const foo2: IFnCall2 = function () {
return ''
}
foo2(() => {
return ''
}, 10)
// ----------------------------------------------------------
// <MyType> 代表函数调用时的类型约束
// 其中第一个参数为一个函数,并且返回值的类型为 MyType
interface IFnCall3 {
<MyType>(fn: () => MyType, age: number): string
}
const foo3: IFnCall3 = function () {
return ''
}
foo3<number>(() => {
return 11
}, 10)
// 报错写法, MyType 类型不一致
// foo3<string>(() => {
// return 11
// }, 10)
// 正确写法
foo3<number>(() => {
return 11
}, 10)
// 不传入类型,则会进行类型推断
foo3(() => {
return 11
}, 10)
// ----------------------------------------------------------
// <MyType> 代表函数调用时的类型约束
// 其中第一个参数为一个函数,并且返回值的类型为 MyType
// IFnCall4 的返回值类型也为 MyType
interface IFnCall4 {
<MyType>(fn: () => MyType, age: number): MyType
}
const foo4: IFnCall4 = function (fn) {
return fn()
}
// 这里对 foo4 的返回值进行类型约束,
foo4<number>(() => {
return 11
}, 10)
// -----------------------------------------------------------
// <MyType> 代表函数调用时的类型约束
// <IRoot> 代表函数定义时的类型约束
interface IFnCall5<IRoot> {
<MyType>(fn: (name: IRoot) => MyType, age: number): MyType
}
const foo5: IFnCall5<string> = function (fn) {
return fn('Tom')
}
// 类型推断过程
// IFnCall5 的 IRoot 定义 string 类型
// 根据 fn 的 name 的 IRoot 类型 推断 fn 函数的返回值 MyType 为 string 类型
// 得到 foo5 函数调用时类型也为 string
// 得到 foo5 函数返回值类型也为 string
// 因此,可以通过fn参数一的返回值推断出 IFnCall5 的返回值类型
const res = foo5((name) => {
return name
}, 10)
console.log(res)