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

TypeScript条件Props问题:必填Props值依赖另一Props

问题分析与解决方案

你的核心问题在于:虽然用联合类型定义了互斥的Props组合,但直接解构后TypeScript无法自动关联mode和variant的类型配对,同时组件调用时的类型检查可能因写法或配置问题未生效。

为什么当前代码不生效?

当你将AcceptedProps(ButtonManager | ButtonEmployee)作为组件参数类型时,TypeScript会把mode推断为'manager' | 'employee',variant推断为所有可选值的联合('primary' | 'secondary' | 'tertiary' | 'primary-dark' | 'primary-light' | 'text')。它不会自动跟踪这两个字段来自联合类型的同一个分支,因此无法在组件内部或调用时自动约束两者的对应关系。

解决方案

1. 组件调用时强制类型关联(泛型方案)

通过泛型让组件的Props类型依赖于mode的值,确保调用时TypeScript能实时校验variant的合法性:

export interface ButtonManager {
  variant: 'primary' | 'secondary' | 'tertiary';
  mode: 'manager';
}

export interface ButtonEmployee {
  variant: 'primary-dark' | 'primary-light' | 'secondary' | 'text';
  mode: 'employee';
}

// 用泛型关联mode和对应的Props类型
type ButtonProps<T extends 'manager' | 'employee'> = 
  T extends 'manager' ? ButtonManager : ButtonEmployee;

export const Button = <T extends 'manager' | 'employee'>({
  mode,
  variant,
  ...props
}: ButtonProps<T>) => {
  // 组件内部逻辑
  if (mode === 'manager') {
    // 此处variant自动被窄化为'manager'专属类型
  } else {
    // 此处variant自动被窄化为'employee'专属类型
  }
  return <button {...props}>{/* 渲染内容 */}</button>;
};

使用示例:

  • 合法调用:<Button mode="manager" variant="primary" /> 或 <Button mode="employee" variant="primary-dark" />
  • 非法调用会直接报错:<Button mode="manager" variant="primary-dark" />(primary-dark不属于manager的variant)

2. 组件内部类型窄化(类型守卫方案)

如果不需要修改组件定义,可在内部通过mode的判断来窄化variant的类型,确保逻辑安全:

type AcceptedProps = ButtonManager | ButtonEmployee

export const Button = ({ mode, variant, ...props }: AcceptedProps) => {
  if (mode === 'manager') {
    // TypeScript此时知道variant是'manager'的专属值
    const managerVariant: ButtonManager['variant'] = variant;
    // 基于managerVariant处理样式
  } else {
    // TypeScript此时知道variant是'employee'的专属值
    const employeeVariant: ButtonEmployee['variant'] = variant;
    // 基于employeeVariant处理样式
  }
  return <button {...props}>{/* 渲染内容 */}</button>;
};

3. 检查TypeScript配置

如果调用时仍未触发类型报错,确保你的tsconfig.json中开启了严格模式:

{
  "compilerOptions": {
    "strict": true,
    // 其他配置...
  }
}

strict模式会启用包括strictFunctionTypes在内的多项严格检查,确保联合类型的配对关系被正确校验。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 19:27:23