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

TypeScript实现任意类型单值通用map转换函数(参考Kotlin作用域函数)

TypeScript 通用单值映射函数实现

针对你想要实现“任意单值通过独立作用域完成转换、复用通用变量命名”的需求,有两种成熟可落地的实现方式,完全匹配你参考的Kotlin作用域函数的行为:

方案1:原型扩展实现(完全匹配你期望的链式调用写法)

这是和你举的变量.map(转换函数)写法完全一致的实现方式,核心逻辑是给所有JS类型的根原型Object.prototype挂载通用的map方法,再补全对应的TS类型声明,即可实现任意类型值直接链式调用映射方法的效果。

实现代码

首先是TS全局类型声明,让TypeScript能识别到这个新增的方法,避免类型报错:

// global.d.ts
declare global {
  interface Object {
    /**
     * 单值通用映射:将当前值作为入参传入转换函数,返回转换后的结果
     * @param transform 接收当前值的转换函数
     */
    map<T, K>(this: T, transform: (value: T) => K): K
  }
}
export {}

然后是原型方法的实际挂载逻辑,放在项目入口文件执行一次即可:

// main.ts 或 全局初始化文件
if (!Object.prototype.map) {
  Object.prototype.map = function<T, K>(this: T, transform: (value: T) => K): K {
    return transform(this)
  }
}

核心特性

  • 类型推导完全正常:转换函数的入参会自动匹配调用map的变量原始类型(字符串、数字等原始值会自动去掉装箱包装,不会被识别成包装对象),返回值会自动推导为转换后的类型
  • 不会覆盖原生数组的map方法:原型链查找顺序为实例 -> Array.prototype -> Object.prototype,数组调用map时会优先走原生数组的映射逻辑,和单值map的行为完全隔离
  • 完全满足作用域隔离需求:传入的转换函数是独立的函数作用域,内部声明的中间变量(比如格式化日期时用到的date、str)不会泄漏到外部作用域,多个转换场景可以复用相同的变量命名,不用为每个场景设计差异化变量名

可选增强:空值兼容

如果需要兼容null/undefined的场景,可以在实现里增加判空逻辑,避免调用时直接抛错:

if (!Object.prototype.map) {
  Object.prototype.map = function<T, K>(this: T, transform: (value: T) => K): K | undefined {
    if (this === null || this === undefined) return undefined
    return transform(this)
  }
}

实际使用效果

实现完成后,你之前写的日期转换代码可以直接正常运行,类型检查完全通过:

data['other']['invoiceDateDotFormat'] = data['invoice']['invoiceDate'].map(
  (dateString) => {
    const date = new Date(dateString)
    let str = ('0' + date.getDate()).slice(-2)
    str += '.' + ('0' + (date.getMonth() + 1)).slice(-2)
    str += '.' + date.getFullYear()
    return str
  },
)

data['other']['purchaseDateDashFormat'] = data['invoice']['purchaseDateDashFormat'].map(
  (dateString) => {
    const date = new Date(dateString)
    let str = ('0' + date.getDate()).slice(-2)
    str += '-' + ('0' + (date.getMonth() + 1)).slice(-2)
    str += '-' + date.getFullYear()
    return str
  },
)

方案2:无原型扩展的纯函数实现(无全局污染,更安全)

如果担心扩展原生原型带来的潜在冲突(比如和第三方库的原型枚举逻辑不兼容、ESLint的no-extend-native规则报错),可以实现独立的泛型纯函数,虽然写法上没有链式调用简洁,但完全没有全局副作用:

/**
 * 通用单值映射函数
 * @param value 待转换的原始值
 * @param transform 转换逻辑函数
 */
function mapValue<T, K>(value: T, transform: (value: T) => K): K {
  return transform(value)
}

实际使用效果

data['other']['invoiceDateDotFormat'] = mapValue(
  data['invoice']['invoiceDate'],
  (dateString) => {
    const date = new Date(dateString)
    let str = ('0' + date.getDate()).slice(-2)
    str += '.' + ('0' + (date.getMonth() + 1)).slice(-2)
    str += '.' + date.getFullYear()
    return str
  },
)

这个实现和Kotlin的let作用域函数行为完全一致,同样能实现临时作用域隔离、复用通用变量命名的核心需求。

注意事项

  • 原型扩展方案需要在项目的ESLint配置中为Object.prototype.map开放白名单,否则会触发禁止修改原生原型的规则报错
  • 给原型挂载方法时不要将方法设置为可枚举属性,否则会影响原生for...in循环的遍历结果

内容的提问来源于stack exchange,提问作者kirtan403

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.28 13:36:05