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

TypeScript中实现与optionalValue同签名的requiredValue报错,如何解决?

解决TypeScript函数重载类型不匹配问题:实现requiredValue辅助函数

问题场景

我正在为Notion API编写属性解析辅助函数,已经用函数重载完成了optionalValue的实现——它能根据指定类型解析值,解析失败时返回undefined:

type Value = { text: string | undefined };

export function optionalValue(value: Value, type: "number"): number | undefined;
export function optionalValue(value: Value, type: "date"): Date | undefined;
export function optionalValue(value: Value, type: "string"): string | undefined;

export function optionalValue(value: Value, type: "number" | "date" | "string") {
  if (type === "number") {
    const number = Number(value.text);
    return isNaN(number) ? undefined : number;
  }

  if (type === "date") {
    const date = value.text ? new Date(value.text) : undefined;
    return date && !isNaN(date.getTime()) ? date : undefined;
  }

  return value.text;
}

接下来我想实现requiredValue,要求它和optionalValue拥有完全一致的签名,但解析失败时抛出错误而非返回undefined。我尝试直接复用optionalValue的类型:

export const requiredValue: typeof optionalValue = (value, type) => {
  const parsedValue = optionalValue(value, type);

  if (parsedValue === undefined) {
    throw new Error(`The ${type} value '${value}' could not be parsed.`);
  }

  return parsedValue;
};

但这段代码触发了TypeScript编译错误:

typescript: No overload matches this call.
  Overload 1 of 3, '(value: Value, type: "number"): number | undefined', gave the following error.
    Argument of type '"string" | "number" | "date"' is not assignable to parameter of type '"number"'.
      Type '"string"' is not assignable to type '"number"'.
  Overload 2 of 3, '(value: Value, type: "date"): Date | undefined', gave the following error.
    Argument of type '"string" | "number" | "date"' is not assignable to parameter of type '"date"'.
      Type '"string"' is not assignable to type '"date"'.
  Overload 3 of 3, '(value: Value, type: "string"): string | undefined', gave the following error.
    Argument of type '"string" | "number" | "date"' is not assignable to parameter of type '"string"'.
      Type '"number"' is not assignable to type '"string"'. [2769]

可行解决方法

方法1:手动为requiredValue定义函数重载

直接为requiredValue编写和optionalValue对应的重载签名,明确每个类型参数对应的非undefined返回值:

// 复用之前定义的Value类型和optionalValue函数

// 手动定义requiredValue的重载
export function requiredValue(value: Value, type: "number"): number;
export function requiredValue(value: Value, type: "date"): Date;
export function requiredValue(value: Value, type: "string"): string;

export function requiredValue(value: Value, type: "number" | "date" | "string") {
  const parsedValue = optionalValue(value, type);

  if (parsedValue === undefined) {
    // 用value.text代替value,避免打印对象[object Object]
    throw new Error(`The ${type} value '${value.text}' could not be parsed.`);
  }

  // 类型断言排除undefined,因为已经做了存在性检查
  return parsedValue as Exclude<ReturnType<typeof optionalValue>, undefined>;
}

这种方式完全贴合原有的重载逻辑,TypeScript能正确识别每个重载分支的参数和返回值类型。

方法2:用泛型+类型映射重构(更简洁可维护)

通过定义一个类型映射表,统一管理类型名称和对应解析结果的类型,避免重复编写重载:

// 定义类型映射表,统一管理类型对应关系
type ValueTypeMap = {
  number: number;
  date: Date;
  string: string;
};

type Value = { text: string | undefined };

// 用泛型重构optionalValue
export function optionalValue<T extends keyof ValueTypeMap>(value: Value, type: T): ValueTypeMap[T] | undefined {
  if (type === "number") {
    const number = Number(value.text);
    return isNaN(number) ? undefined : number as ValueTypeMap[T];
  }

  if (type === "date") {
    const date = value.text ? new Date(value.text) : undefined;
    return (date && !isNaN(date.getTime()) ? date : undefined) as ValueTypeMap[T];
  }

  return value.text as ValueTypeMap[T] | undefined;
}

// 用泛型实现requiredValue
export function requiredValue<T extends keyof ValueTypeMap>(value: Value, type: T): ValueTypeMap[T] {
  const parsedValue = optionalValue(value, type);

  if (parsedValue === undefined) {
    throw new Error(`The ${type} value '${value.text}' could not be parsed.`);
  }

  return parsedValue;
}

这种方式的优势在于:后续新增类型时,只需要修改ValueTypeMap和optionalValue的逻辑,不需要重复编写重载签名,代码的可维护性更高。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 09:27:02