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

如何编写TS函数:接收多类型输入,返回string|null/undefined?

如何编写满足特定类型约束的TypeScript格式化函数

我需要编写一个TypeScript函数,它接受string|number|null|undefined类型的参数,但仅返回string或对应的null|undefined类型。

我尝试实现了toLocaleString1函数,但它会出现编译错误,只有通过大量类型断言(比如toLocaleString2的写法)才能正常编译。但我认为已经做了null和undefined的检查,没必要用这些断言。

我的代码逻辑分析

  1. 空值检查:
if (value === null || value === undefined) return value;

这一步之后,value的类型应该被收窄为null|undefined,返回值类型应该和输入泛型T一致。比如传入string|null类型的变量,返回类型应该是string|null——如果输入是string则返回格式化后的string,如果是null则直接返回null。

我原本用这个条件类型定义返回值:
T extends (string|number) ? string : never | Exclude<T, number>

  1. 解析数字:
const nr = parseFloat(value as string);

这里必须加类型断言,因为parseFloat对null、undefined和非数字值只会返回NaN,不过其实前面的空值检查在技术层面并非必需。

  1. 处理非有效数字:
if(!isFinite(nr)) return value.toString();

这一步时value已经是string|number类型,我们将其转为string返回(如果是number类型的话)。

  1. 返回本地化字符串:
return nr.toLocaleString(locale);

这里同样返回string类型,此时输入必然是string|number类型,理论上应该可以正常运行。

核心疑问

toLocaleString1的问题出在哪里?它为什么不能正常编译?我测试了各种输入的类型推断结果,都符合预期,两个函数运行时功能完全正常,但第一个就是会报编译错误。

目标重载行为

我希望函数支持以下重载:

  • string => string
  • string | null => string | null
  • string | null | undefined => string | null | undefined
  • string | undefined => string | undefined
  • string | number => string
  • string | number | null => string | null
  • string | number | null | undefined => string | null | undefined
  • string | number | undefined => string | undefined
  • number | null => string | null
  • number | null | undefined => string | null | undefined
  • number | undefined => string | undefined
  • null | undefined => null | undefined
  • null => null
  • undefined => undefined

完整代码示例

// 编译报错:
function toLocaleString1<T extends number|string|null|undefined>(value: T, locale?: string): T extends (string|number) ? string : never | Exclude<T, number> {
  if (value === null || value === undefined) return value;
  const nr = parseFloat(value as string);
  if(!isFinite(nr)) return value.toString();
  return nr.toLocaleString(locale);
}

// 功能相同但使用了大量类型断言:
function toLocaleString2<T extends number|string|null|undefined, R extends (T extends (string|number) ? string : never | Exclude<T, number>) >(value: T, locale?: string): R {
  const nr = parseFloat(value as string);
  if(!isFinite(nr)) return `${value}` as unknown as R;
  return nr.toLocaleString(locale) as unknown as R;
}

const TYPES = ['string', 'number', 'null', 'undefined', 'NaN'] as const;

function value(type: (typeof TYPES)[number] ) : string | number | null | undefined {
  switch(type) {
    case 'string': return "12345.678"; 
    case 'number': return 98765.4321; 
    case 'null': return null; 
    case 'undefined': return undefined; 
    case 'NaN': return NaN; 
  }
}

console.log('-------------')
for (const type of TYPES) {
  const input = value(type);
  const formatted1 = toLocaleString1(input, 'de');
  const formatted2 = toLocaleString2(input, 'fr');
  console.log(type, input, formatted1, formatted2);
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 02:20:04