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

TypeScript如何定义值为不同强类型函数的字典类型?

解决方案

可以实现需求,核心思路是不要提前给DICT声明统一的索引类型(会覆盖掉每个项的独有类型),而是通过类型约束既保证结构符合要求,又保留每个greeter函数的具体参数、返回值类型。


方案1:TS 4.9及以上版本使用satisfies操作符

satisfies可以在不丢失变量原始类型的前提下,验证变量是否符合指定的类型约束,是当前最优实现:

export enum SomeKeys {
  FIRST_KEY = 'FIRST_KEY',
  SECOND_KEY = 'SECOND_KEY',
}

// 定义字典项的基础约束结构
type DictItemBase = {
  title: string;
  greeter: (...args: any[]) => any;
}

export const DICT = {
  [SomeKeys.FIRST_KEY]: {
    title: 'first key title',
    greeter: (name: string) => ({ name }),
  },
  [SomeKeys.SECOND_KEY]: {
    title: 'second key title',
    greeter: (name: string, age: number) => ({
      name,
      age,
    }),
  },
// 约束所有枚举key都存在,且结构符合DictItemBase要求
} satisfies Record<SomeKeys, DictItemBase>;

使用时可以正确推导类型:

const { title, greeter } = DICT[SomeKeys.FIRST_KEY];
// greeter自动推导为 (name: string) => { name: string }
const { name } = greeter('Adam'); // 无类型报错,返回值属性可正常识别

const { greeter: secondGreeter } = DICT[SomeKeys.SECOND_KEY];
// secondGreeter自动推导为 (name: string, age: number) => { name: string; age: number }
const { age } = secondGreeter('Bob', 20); // 正常校验参数数量、类型,识别返回值

方案2:TS 4.9以下版本兼容方案

如果你的TS版本不支持satisfies,可以用泛型函数来实现同样的类型保留效果:

export enum SomeKeys {
  FIRST_KEY = 'FIRST_KEY',
  SECOND_KEY = 'SECOND_KEY',
}

type DictItemBase = {
  title: string;
  greeter: (...args: any[]) => any;
}

// 用泛型函数做类型约束
function defineDict<T extends Record<SomeKeys, DictItemBase>>(dict: T) {
  return dict;
}

export const DICT = defineDict({
  [SomeKeys.FIRST_KEY]: {
    title: 'first key title',
    greeter: (name: string) => ({ name }),
  },
  [SomeKeys.SECOND_KEY]: {
    title: 'second key title',
    greeter: (name: string, age: number) => ({ name, age }),
  },
});

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 07:45:03