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

如何用泛型为TypeScript嵌套函数返回值做类型安全标注?

问题描述

我有一个关联对应类型的映射器,但不知道如何正确为其中的func标注类型,相关代码如下:

type Action<T, K> = {
  key: K;
  func: // What should this be?
};

type ActionMapper<T> = {
  [K in keyof T]: Action<T, K>;
}; 

export enum EActionSelectPot {
  CREATE_ORDER = 'CREATE_ORDER',
  ADD_ITEM = 'ADD_ITEM',
  DELETE_ORDER = 'DELETE_ORDER',
}

const first_function = () => 'hi';
const second_function = () => ['hi'];
const third_function = () => {
  hi: 'hi';
};

const test: ActionMapper<typeof EActionSelectPot> = {
  CREATE_ORDER: {
    key: EActionSelectPot.CREATE_ORDER,
    func: first_function,
  },
  ADD_ITEM: {
    key: EActionSelectPot.ADD_ITEM,
    func: second_function,
  },
  DELETE_ORDER: {
    key: EActionSelectPot.DELETE_ORDER,
    func: third_function,
  },
};

const hi = test.CREATE_ORDER.func();

我的目标是通过泛型让该对象自动推断函数类型,无需手动指定返回类型。不确定该需求是否可行,若可行该如何实现?曾尝试func: () => ReturnType[K]['func']>但未成功,希望得到实现方向指引。

实现方案

你的需求完全可行,核心是调整泛型类型的设计逻辑,让TypeScript能关联枚举键与对应函数的类型信息。

方案1:重构泛型类型,明确函数关联

先修改Action和ActionMapper的泛型定义,让它们能接收并关联每个枚举键对应的函数类型:

// 单个Action类型:绑定枚举键K和对应的函数类型F
type Action<K extends string | number | symbol, F extends (...args: any[]) => any> = {
  key: K;
  func: F;
};

// ActionMapper接收函数映射类型,自动生成对应结构
type ActionMapper<T extends Record<string | number | symbol, (...args: any[]) => any>> = {
  [K in keyof T]: Action<K, T[K]>;
};

接着定义枚举对应的函数映射,再约束test变量:

export enum EActionSelectPot {
  CREATE_ORDER = 'CREATE_ORDER',
  ADD_ITEM = 'ADD_ITEM',
  DELETE_ORDER = 'DELETE_ORDER',
}

const first_function = () => 'hi';
const second_function = () => ['hi'];
// 修复原代码语法错误:对象字面量需加括号或return
const third_function = () => ({ hi: 'hi' });

// 定义枚举键与函数的映射类型
type ActionFunctions = {
  [EActionSelectPot.CREATE_ORDER]: typeof first_function;
  [EActionSelectPot.ADD_ITEM]: typeof second_function;
  [EActionSelectPot.DELETE_ORDER]: typeof third_function;
};

// 自动推断每个func的类型
const test: ActionMapper<ActionFunctions> = {
  CREATE_ORDER: {
    key: EActionSelectPot.CREATE_ORDER,
    func: first_function,
  },
  ADD_ITEM: {
    key: EActionSelectPot.ADD_ITEM,
    func: second_function,
  },
  DELETE_ORDER: {
    key: EActionSelectPot.DELETE_ORDER,
    func: third_function,
  },
};

// 此时func返回类型已被正确推断
const hi = test.CREATE_ORDER.func(); // 类型为string

方案2:用泛型函数自动推导(更简洁)

无需手动定义函数映射类型,用泛型函数辅助创建对象,让TypeScript自动完成所有类型推断:

function createActionMapper<T>(mapper: T): T {
  return mapper;
}

// 直接创建对象,所有类型自动推断
const test = createActionMapper({
  CREATE_ORDER: {
    key: EActionSelectPot.CREATE_ORDER,
    func: first_function,
  },
  ADD_ITEM: {
    key: EActionSelectPot.ADD_ITEM,
    func: second_function,
  },
  DELETE_ORDER: {
    key: EActionSelectPot.DELETE_ORDER,
    func: third_function,
  },
});

// 同样能正确识别每个func的返回类型
const items = test.ADD_ITEM.func(); // 类型为string[]
const order = test.DELETE_ORDER.func(); // 类型为{ hi: string }

原尝试失败原因分析

你之前写的func: () => ReturnType[K]['func']>不可行,是因为:

  • K是枚举的键(如CREATE_ORDER)本身不是函数类型,ReturnType需要传入函数类型才能生效
  • 原ActionMapper仅关联了枚举类型,没有绑定每个键对应的函数信息,TypeScript无法获取函数的返回类型

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 16:08:16