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

TypeScript中如何正确标注flexifyParams函数的返回值类型

如何为flexifyParams函数正确标注TypeScript返回值类型?

问题背景

我正在编写一个TypeScript模块,其中包含flexifyParams函数:该函数接收一个对象,会调用对象中所有函数类型的属性,并将返回值赋值给对应属性;若属性非函数类型则直接保留原值。

JavaScript实现源码

import _ from 'lodash'

export default function flexifyParams(params) {
  const composedObject = {}
  for (const [key, value] of Object.entries(params)) {
    composedObject[key] = _.isFunction(value) ? value() : value
  }
  return composedObject
}

使用示例

const test = {
  x: () => 'hi',
  y: () => 123,
  z: () => ["a", "b", "c"],
  a: 'my string',
}
const P = flexifyParams(test)

// P 等于:
//  {
//     x: 'hi',
//     y: 123,
//     z: ["a", "b", "c"],
//     a: 'my string',
//   }

当前TypeScript版本(存在类型问题)

import _ from 'lodash'

export default function flexifyParams<PARAMS extends object>(params: PARAMS): PARAMS {
  const composedObject: { [index: string]: string | Symbol | number } = {}
  for (const [key, value] of Object.entries(params)) {
    composedObject[key] = _.isFunction(value) ? value() : value
  }
  return composedObject as PARAMS
}

当前代码可正常运行,但返回值类型标注存在问题:返回对象的键与输入对象一致,但值类型应为对应函数属性的返回值,而非原属性类型。


解决方案

要解决这个问题,我们需要使用TypeScript的映射类型和条件类型,为返回值生成精确的类型:

核心思路

遍历输入对象的每个键,对每个属性值做判断:

  • 如果属性是无参函数类型,提取它的返回值类型作为新属性的类型
  • 如果属性不是函数类型,直接保留原类型

完整TypeScript实现

import _ from 'lodash'

// 定义映射类型:将函数属性替换为其返回值类型,非函数属性保留原类型
type ResolvedParams<PARAMS extends object> = {
  [K in keyof PARAMS]: PARAMS[K] extends () => infer R ? R : PARAMS[K]
}

export default function flexifyParams<PARAMS extends object>(params: PARAMS): ResolvedParams<PARAMS> {
  // 使用映射类型定义composedObject,避免类型过宽
  const composedObject: Partial<ResolvedParams<PARAMS>> = {}
  
  for (const [key, value] of Object.entries(params)) {
    // 类型断言key为PARAMS的键,避免Object.entries的类型丢失
    const typedKey = key as keyof PARAMS
    composedObject[typedKey] = _.isFunction(value) ? value() : value as ResolvedParams<PARAMS>[typeof typedKey]
  }
  
  // 断言为完整的ResolvedParams类型,因为我们遍历了所有键
  return composedObject as ResolvedParams<PARAMS>
}

类型验证

使用之前的测试示例,TypeScript会自动推导P的类型为:

{
  x: string;
  y: number;
  z: string[];
  a: string;
}

完全符合函数实际的返回值结构。


内容的提问来源于stack exchange,提问作者Islam Y-

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 21:12:44