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

TypeScript中函数类型映射与参数类型的匹配问题

解决方案

要解决这个类型安全问题,不用as any绕过检查,我们可以通过以下两种方式优化:

方式一:精确类型断言替代any

首先明确:BlendedProps<T>是{key: T; z?: string; x?: string}与typeMap[T]的交叉类型,而typeMap[T]的键名并不包含key/z/x,因此解构后的rest类型本质上就是typeMap[T]。我们可以直接用这个精确类型做断言,而非any:

interface OneFProps {
  a: string;
  b: string;
}

const oneF = (props: OneFProps) => {
  const { a, b } = props;
  return `oneF ${a} ${b}`;
};

interface TwoFProps {
  c: string;
  d: string;
}

const twoF = (props: TwoFProps) => {
  const { c, d } = props;
  return `twoF ${c} ${d}`;
};

const funcMap = {
  oneF: oneF,
  twoF: twoF,
};

interface typeMap {
  oneF: OneFProps;
  twoF: TwoFProps;
}

type tags = keyof typeMap;

type BlendedProps<T extends tags> = {
  key: T;
  z?: string;
  x?: string;
} & typeMap[T];

const blended = <T extends tags>(props: BlendedProps<T>) => {
  const { key, z, x, ...rest } = props;
  const func = funcMap[key];
  // 用精确的typeMap[T]替代any,保持类型安全
  return func(rest as typeMap[T]);
};

console.log(blended<'oneF'>({ key: 'oneF', a: 'AAA', b: 'bbb' }));
console.log(blended<'twoF'>({ key: 'twoF', c: 'ccc', d: 'DDD' }));

方式二:自动推导类型映射,减少手动维护

手动维护typeMap容易和funcMap不一致,我们可以让TypeScript自动从函数映射对象推导参数类型,同时优化泛型逻辑:

interface OneFProps {
  a: string;
  b: string;
}

const oneF = (props: OneFProps) => {
  const { a, b } = props;
  return `oneF ${a} ${b}`;
};

interface TwoFProps {
  c: string;
  d: string;
}

const twoF = (props: TwoFProps) => {
  const { c, d } = props;
  return `twoF ${c} ${d}`;
};

// 用as const锁定funcMap的类型,确保推导精确
const funcMap = {
  oneF,
  twoF,
} as const;

// 自动推导函数映射的类型
type FuncMap = typeof funcMap;
type tags = keyof FuncMap;
// 自动推导每个函数对应的参数类型
type typeMap = {
  [K in tags]: Parameters<FuncMap[K]>[0];
};

type BlendedProps<T extends tags> = {
  key: T;
  z?: string;
  x?: string;
} & typeMap[T];

const blended = <T extends tags>(props: BlendedProps<T>) => {
  const { key, z, x, ...rest } = props;
  const func = funcMap[key];
  return func(rest as typeMap[T]);
};

console.log(blended({ key: 'oneF', a: 'AAA', b: 'bbb' })); // 可省略泛型参数,TypeScript自动推导
console.log(blended({ key: 'twoF', c: 'ccc', d: 'DDD' }));

原代码需要as any的原因

原代码中,TypeScript对泛型交叉类型的剩余属性推导不够精确:当你从BlendedProps<T>解构出rest时,它的类型被推断为Pick<BlendedProps<T>, Exclude<keyof BlendedProps<T>, 'key' | 'z' | 'x'>>,虽然这个类型本质上等于typeMap[T],但TypeScript无法在泛型上下文里自动确认这一点,因此需要我们用精确的类型断言来帮助它完成推导。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 13:06:25