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

TypeScript中如何正确推断作为入参传入的函数的参数类型

问题背景
  • 需求:实现支持可选第二参数的useTheme函数,传入样式函数后,useTheme需要根据样式函数的参数类型,自动校验自身styleProps入参的静态类型。
  • 原有实现存在类型推断缺陷:当样式函数的第二参数是联合类型时,合法传参会被标记为类型错误。

原有问题代码如下:

type StylingFn<T, P> = (
    theme: Theme,
    ...props: P extends undefined ? [undefined?] : [P]
) => StyleProp<T>;

const useTheme = <T, P = undefined>(
    styles: StylingFn<T, P>,
    ...styleProps: P extends undefined ? [undefined?] : [P]
) => {
    const theme: Theme = {}; // 示例代码
    return styles(theme, ...styleProps);
};

// 问题复现
const Union = "a" | "b";
const s1 = (theme: Theme) => ({});
const s2 = (theme: Theme, {c}: {c: number}) => ({});
const s3 = (theme: Theme, {c}: {c: Union}) => ({});

useTheme(s1); // 校验通过
useTheme(s2, {c: 12}); // 校验通过
useTheme(s3, {c: "a"}); // 误报错误
问题原因

原有实现通过独立泛型P同时约束StylingFn和styleProps的类型,TypeScript在类型推断阶段会优先匹配StylingFn的类型结构,遇到联合类型等复杂类型时会出现推断偏差,丢失类型信息,导致校验错误。

修复方案

通过infer关键字直接从传入的样式函数中提取剩余参数类型,避免提前用泛型约束打断类型推断链路,完整保留参数的原始类型信息。

type Theme = Record<string, any>;
type StyleProp<T> = T;

// 从传入的样式函数中提取额外参数类型
type ExtractStyleProps<StyleFn> = StyleFn extends (theme: Theme, ...args: infer Props) => StyleProp<any>
  ? Props
  : never;

const useTheme = <StyleFn extends (theme: Theme, ...args: any[]) => StyleProp<any>>(
  styles: StyleFn,
  ...styleProps: ExtractStyleProps<StyleFn>
) => {
  const theme: Theme = {}; // 业务逻辑替换为实际theme获取逻辑
  return styles(theme, ...styleProps);
};
验证结果

以下用例均符合类型校验预期:

const Union = "a" | "b";

const s1 = (theme: Theme) => ({});
const s2 = (theme: Theme, {c}: {c: number}) => ({});
const s3 = (theme: Theme, {c}: {c: Union}) => ({});

useTheme(s1); // 校验通过
useTheme(s2, {c: 12}); // 校验通过
useTheme(s3, {c: "a"}); // 校验通过
useTheme(s3, {c: "c"}); // 正常报错:类型"c"不在联合类型"a"|"b"范围内

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 20:27:16