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

如何让TypeScript保留React依赖props在展开时的关联关系?

React组件Props依赖关系展开时的TypeScript类型问题

我有一些React组件,接收两个存在依赖关系的props:当a为'foo'时,b必须是{ foo: number };当a为'bar'时,b必须是{ bar: number }。组件类型定义如下:

function Component<
  A,
  B extends (A extends 'foo' ? { foo: number } : { bar: number })
>(props: {
  a: A,
  b: B,
}) {}

<Component a="foo" b={{ foo: 1 }} /> // 合法
<Component a="bar" b={{ foo: 1 }} /> // 类型错误

我写了一个辅助函数返回这组props:

function getProps() {
  return Math.random() > 0.5
    ? { a: 'foo', b: { foo: 1 } }
    : { a: 'bar', b: { bar: 1 } };
}

这个函数的返回类型被TypeScript推断为:

{ a: 'foo', b: { foo: number, bar?: undefined } }
| { a: 'bar', b: { bar: number, foo?: undefined } }

但当我尝试使用<Component {...getProps()} />时,会出现类型错误,原因是TypeScript将联合类型拆解成了:

{
  a: 'foo' | 'bar',
  b: { foo: number, bar?: undefined } | { bar: number, foo?: undefined }
}

丢失了a和b之间的依赖关联。


简便解决方案

方法1:显式定义合法Props的联合类型

先定义组件接受的两种合法props组合,再让辅助函数返回这个类型,强制TypeScript保留联合成员的内部关联:

// 定义合法的props联合类型
type ValidComponentProps = 
  | { a: 'foo', b: { foo: number } }
  | { a: 'bar', b: { bar: number } };

function getProps(): ValidComponentProps {
  return Math.random() > 0.5
    ? { a: 'foo', b: { foo: 1 } }
    : { a: 'bar', b: { bar: 1 } };
}

// 此时展开不会报错
<Component {...getProps()} />

方法2:调用时使用类型断言

如果不想修改辅助函数,可以在展开时断言为合法的联合类型:

type ValidComponentProps = 
  | { a: 'foo', b: { foo: number } }
  | { a: 'bar', b: { bar: number } };

<Component {...getProps() as ValidComponentProps} />

方法3:用as const缩小返回值类型

通过as const让TypeScript精确推断返回值的字面量类型,保留a和b的关联:

function getProps() {
  return Math.random() > 0.5
    ? ({ a: 'foo', b: { foo: 1 } } as const)
    : ({ a: 'bar', b: { bar: 1 } } as const);
}

// 若组件不接受readonly类型的props,可进一步调整为:
function getProps() {
  return Math.random() > 0.5
    ? { a: 'foo' as const, b: { foo: 1 } }
    : { a: 'bar' as const, b: { bar: 1 } };
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 23:33:22