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

如何让TypeScript根据prefix参数返回正确类型的对象?

TypeScript根据prefix参数推导返回类型的实现方法

你可以通过泛型+条件类型+模板字面量类型实现这个需求,让TypeScript根据prefix参数的有无自动推断返回对象的类型。

修改后的代码实现

import { format } from 'date-fns';
// 假设以下依赖已定义
declare function formatDay(date: string): string;
declare const i18n: {
  t(key: string, opts: { returnObjects: true }): any;
};

function getOptions<
  P extends string | undefined = undefined
>(
  period: { first: string; last: string },
  prefix?: P
): P extends string 
  ? { [K in `${P}_first` | `${P}_last` | `${P}_month`]: string }
  : { first: string; last: string; month: string } {
  if (prefix) {
    return {
      [`${prefix}_first`]: formatDay(period.first),
      [`${prefix}_last`]: formatDay(period.last),
      [`${prefix}_month`]: format(new Date(), 'MMMM', {
        locale: i18n.t('datefns:format', { returnObjects: true }),
      }),
    } as ReturnType<typeof getOptions<P>>;
  }

  return {
    first: formatDay(period.first),
    last: formatDay(period.last),
    month: format(new Date(), 'MMMM', {
      locale: i18n.t('datefns:format', { returnObjects: true }),
    }),
  } as ReturnType<typeof getOptions<P>>;
}

关键逻辑说明

  1. 泛型参数约束:P extends string | undefined 限定prefix的类型范围,默认值设为undefined对应不传参数的场景。
  2. 条件返回类型:通过P extends string ? ... : ...分支判断,分别生成两种结构的返回类型:
    • 当prefix为字符串时,用模板字面量类型${P}_first生成带前缀的键名,结合映射类型构建对应结构。
    • 当prefix不存在时,返回固定结构的类型{ first: string; last: string; month: string }。
  3. 类型断言:由于TypeScript对动态键名的推断存在限制,通过as ReturnType<typeof getOptions<P>>让返回值与定义的类型对齐。

验证效果

调用函数时,TypeScript会自动推导正确的返回类型:

// 返回类型:{ first: string; last: string; month: string }
const opt1 = getOptions({ first: '01', last: '10' });

// 返回类型:{ christmas_first: string; christmas_last: string; christmas_month: string }
const opt2 = getOptions({ first: '01', last: '10' }, 'christmas');

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 17:47:48