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

TypeScript中如何根据参数值正确确定函数返回类型?解决预设参数的函数类型标注问题

Fixing TypeScript Type Inference for applyPreset Function

Let's resolve the TypeScript warnings and ensure proper return type deduction for your applyPreset function. The core problem is that TypeScript can't automatically narrow the generic T to distinguish between DatePreset.Custom and other presets, nor can it align the returned value with your conditional return type.

Corrected Code

export enum DatePreset {
  Today = "Today",
  ThisMonth = "This month",
  ThisYear = "This year",
  Custom = "Custom"
}

export interface DateRange {
  from: Date;
  to?: Date;
}

export interface DateRangeWithPreset extends DateRange {
  preset: DatePreset;
}

// Extract the conditional return type into a reusable alias for clarity
type ApplyPresetResult<T extends DatePreset> = 
  T extends DatePreset.Custom ? undefined : Required<DateRangeWithPreset>;

export function applyPreset<T extends DatePreset>(
  preset: T
): ApplyPresetResult<T> {
  const presets: Record<
    Exclude<DatePreset, DatePreset.Custom>,
    Required<DateRange>
  > = {
    [DatePreset.Today]: { from: new Date(), to: new Date() },
    [DatePreset.ThisMonth]: { from: new Date(), to: new Date() },
    [DatePreset.ThisYear]: { from: new Date(), to: new Date() }
  };

  // Explicitly handle the Custom case first
  if (preset === DatePreset.Custom) {
    // Assert this return matches the conditional type for Custom
    return undefined as ApplyPresetResult<T>;
  }

  // Narrow the preset type to exclude Custom, so TypeScript recognizes it's a valid key in presets
  const validPreset = preset as Exclude<DatePreset, DatePreset.Custom>;
  const readyPreset = presets[validPreset];

  // Construct and assert the result matches the conditional return type for non-Custom presets
  return { preset, ...readyPreset } as ApplyPresetResult<T>;
}

// Now TypeScript correctly infers the types:
const validUndefinedRange = applyPreset(DatePreset.Custom); // Type: undefined
const thisYearRange = applyPreset(DatePreset.ThisYear); // Type: Required<DateRangeWithPreset>

console.log("validUndefinedRange", validUndefinedRange);
console.log("thisYearRange", thisYearRange);

Key Changes Explained

  1. Explicit Custom Branch Handling
    By checking preset === DatePreset.Custom first, we give TypeScript a clear code path for the undefined return case. The type assertion tells TypeScript this return value aligns with the conditional type for T = DatePreset.Custom.

  2. Narrowing Preset Type
    We assert preset as Exclude<DatePreset, DatePreset.Custom> after the Custom check. This lets TypeScript know that validPreset is definitely a key present in the presets record, eliminating the indexing error.

  3. Reusable Return Type Alias
    Extracting ApplyPresetResult<T> makes the code cleaner and ensures consistency between the function's return type annotation and the assertions inside the function.

  4. Result Type Assertion
    Finally, we assert the constructed result object matches the ApplyPresetResult<T> type. This bridges the gap between TypeScript's ability to infer the object's structure and your conditional return type requirement.

Now all TypeScript and ESLint warnings should be gone, and the return types will be correctly inferred for every call to applyPreset.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.27 16:52:33