You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

自返回复杂函数的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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 08:49:17