自返回复杂函数的TypeScript类型声明及JavaScript实现技术问询
TypeScript类型声明方案:返回带额外属性的函数
我来帮你搞定这个TypeScript类型声明的问题!先看你提供的JavaScript函数,它的逻辑很有意思——接收一个对象,确保该对象有main方法(没有就创建默认的alert函数),然后把对象的所有属性都挂载到这个main方法上,最后返回这个既是函数、又拥有原对象所有属性的特殊值:
var scopeFunction = (object) => { // 若主函数不存在则创建 if (!object.main) object.main = function(){ alert("No main function for this scopeFunction"); }; // 将对象所有属性添加到要返回的主函数上 _.each(object, function(d,i){ object.main[i] = d; }); // 返回主函数 return object.main; }
要给这个函数写TypeScript类型声明,核心就是要准确描述返回值的双重特性:它是个函数,同时还带着原对象的所有属性。我们可以用泛型+交叉类型来实现,具体步骤如下:
1. 定义泛型与类型约束
首先用泛型捕获传入对象的具体类型,同时处理main属性不存在时的默认函数类型:
import _ from 'lodash'; // 定义默认的main函数类型 type DefaultMainFn = () => void; // 泛型函数的类型声明与实现 function scopeFunction<T extends object>(object: T): // 交叉类型:函数类型(优先取传入对象的main,没有则用默认) + 原对象的所有属性 (T extends { main: infer Fn } ? Fn : DefaultMainFn) & T { // 运行时确保main存在且是函数 if (!('main' in object) || typeof object.main !== 'function') { // 类型断言告诉TS:此时object已经有了DefaultMainFn类型的main (object as T & { main: DefaultMainFn }).main = () => { alert("No main function for this scopeFunction"); }; } // 将对象所有属性挂载到main函数上 _.each(object, (value, key) => { // 类型断言:main现在同时拥有原对象的所有属性 (object.main as typeof object.main & T)[key] = value; }); // 最后返回时做类型断言,确保TS识别到返回值的双重特性 return object.main as (T extends { main: infer Fn } ? Fn : DefaultMainFn) & T; }
2. 类型逻辑说明
- 泛型
T:用来精准捕获传入对象的具体类型,约束为object保证参数是对象类型 - 交叉类型
&:让返回值同时具备「函数能力」和「原对象所有属性」,完美匹配你的函数行为 - 条件类型
T extends { main: infer Fn } ? Fn : DefaultMainFn:自动判断传入对象是否有main属性——如果有就复用它的类型,没有就用默认的alert函数类型 - 类型断言:因为我们在运行时已经确保了
main的存在和类型,所以用断言告诉TypeScript不用再报错啦
3. 使用示例
来试试这个类型声明的效果,TypeScript会完美推断所有类型:
// 示例1:传入带自定义main的对象 const myScope = scopeFunction({ main: () => console.log('Custom main function'), username: 'Alice', age: 28 }); myScope(); // 调用main,输出"Custom main function" console.log(myScope.username); // 访问属性,输出"Alice" console.log(myScope.age); // 输出28 // 示例2:传入不带main的对象 const defaultScope = scopeFunction({ message: 'Hello from scope!' }); defaultScope(); // 弹出alert提示 console.log(defaultScope.message); // 输出"Hello from scope!"
这样写出来的类型声明完全贴合你这个函数的行为,TypeScript会正确提示返回值的所有方法和属性~
内容的提问来源于stack exchange,提问作者chateau
相关产品推荐
相关产品推荐

