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

TypeScript中处理${string} ${string}类型时pop的类型安全问题求解

解决FullName类型的类型安全纯函数问题

问题分析

你定义的FullName = ${string} ${string}``在类型层面保证了字符串包含至少一个空格,但TypeScript无法自动关联split(' ')的结果与原类型的约束,导致pop()返回string|undefined。下面是几种优雅的类型安全解决方案:


方案1:解构赋值+非空断言(简洁版)

如果你的FullName严格要求单个空格分隔两个非空字符串,可以先修正类型定义确保前后部分非空,再用解构直接获取姓氏:

// 定义非空字符串类型,避免空字符串的情况
type NonEmptyString = string & { readonly __brand: unique symbol };
const nonEmptyString = (s: string): NonEmptyString => {
  if (s.trim() === '') throw new Error('字符串不能为空');
  return s as NonEmptyString;
};

// 严格的FullName类型:单个空格分隔两个非空字符串
type FullName = `${NonEmptyString} ${NonEmptyString}`;

const getLastName = (name: FullName): string => {
  const [, lastName] = name.split(' ');
  // 由于FullName的类型约束,lastName必然存在且非空
  return lastName!;
};

优点:代码简洁,类型约束严格,避免运行时传入无效值。


方案2:类型工具+运行时边缘处理(健壮版)

如果需要兼容中间多个空格的场景(比如"John Doe"),可以用类型工具提取姓氏,同时在运行时从后往前过滤空字符串:

type FullName = `${string} ${string}`;

// 类型工具:从FullName中提取姓氏部分
type ExtractLastName<T extends FullName> = T extends `${infer _First} ${infer Last}` ? Last : never;

const getLastName = <T extends FullName>(name: T): ExtractLastName<T> => {
  const parts = name.split(' ');
  let lastName = parts.pop();
  
  // 过滤拆分后可能出现的空字符串(处理多个空格的情况)
  while (lastName === '' || lastName === undefined) {
    lastName = parts.pop();
  }
  
  // 类型断言:由于FullName的约束,lastName必然存在
  return lastName as ExtractLastName<T>;
};

优点:兼顾类型精确推导和运行时健壮性,支持多个空格的场景。


方案3:正则匹配(简洁健壮版)

用正则匹配最后一个空格后的非空内容,同时利用类型约束确保匹配结果存在:

type FullName = `${string} ${string}`;

const getLastName = (name: FullName): string => {
  // 匹配最后一个空格后的所有非空白字符
  const matchResult = name.match(/\s(\S+)$/);
  
  // 由于FullName的类型保证了存在空格和后续内容,matchResult必然有值
  return matchResult![1];
};

优点:代码简洁,自动处理多个空格的情况,类型安全。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 20:48:22