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

Typescript函数参数为两个接口之一时类型不匹配报错如何解决

错误内容如下:

Type '(results: IVoucherScanResults) => IParsedScanResults' is not assignable to type '(results: IBlinkCardScanResults | IVoucherScanResults) => IParsedScanResults'.
  Types of parameters 'results' and 'results' are incompatible.
    Type 'IBlinkCardScanResults | IVoucherScanResults' is not assignable to type 'IVoucherScanResults'.
      Type 'IBlinkCardScanResults' is missing the following properties from type 'IVoucherScanResults': text, timestamp, format, numBitsts(2322)

错误原因

你在IScanFormProps中定义的parseScanResults函数要求可以接收IBlinkCardScanResults | IVoucherScanResults两种类型的参数,但你实际传入CreditCardBarcodeForm的parseScanResults只支持接收IVoucherScanResults单种类型。TypeScript做类型校验时,认为如果后续传入IBlinkCardScanResults类型的参数,当前的parseScanResults无法处理,因此抛出了类型不兼容的错误。

解决方案

方案1:将ScanForm改造为泛型组件(最推荐)

适合需要适配多种扫描结果类型的场景,通过泛型动态约束入参类型:
首先修改ScanForm的类型定义:

// 定义泛型T,约束为两种扫描结果的联合类型
interface IScanFormProps<T extends IVoucherScanResults | IBlinkCardScanResults> {
  children: (props: IScannerProps<T>) => React.ReactElement;
  onSubmit: (data: { expMonth: string; expYear: string; securityCode: string; cardNumber: string }) => void;
  parseScanResults: (results: T) => IParsedScanResults;
}

interface IScannerProps<T extends IVoucherScanResults | IBlinkCardScanResults> {
  scannerActive: boolean;
  closeScanner: () => void;
  handleScanResults: (results: T) => void;
}

// 组件声明时传入泛型
const ScanForm = <T extends IVoucherScanResults | IBlinkCardScanResults>({ 
  children, 
  onSubmit, 
  parseScanResults 
}: IScanFormProps<T>) => {
  const [scannerActive, toggleScannerActive] = useState(false);

  const closeScanner = (): void => {
    toggleScannerActive(false);
  };

  const handleScanResults = (results: T): void => {
    const { cardString, stringMonth, stringYear } = parseScanResults(results);

    setValue('cardNumber', cardString);
    setValue('expMonth', stringMonth);
    setValue('expYear', stringYear);

    toggleScannerActive(false);
  };

  return (
    <Form onSubmit={handleSubmit(onSubmit)}>
      {children({ scannerActive, closeScanner, handleScanResults })}
    </Form>
  );
};

使用时无需额外改动,TypeScript会自动推断泛型类型为IVoucherScanResults,不会再抛出错误。

方案2:为parseScanResults添加类型收窄逻辑

如果不需要泛型,也可以直接修改传入的parseScanResults,让它支持处理两种类型的入参,符合类型定义要求:

const parseScanResults = (results: IVoucherScanResults | IBlinkCardScanResults): IParsedScanResults => {
  // 判断是否是IVoucherScanResults类型
  if ('text' in results) {
    const { text } = results;
    const [cardString, expirationString] = text.slice().split('/');
    const stringMonth = expirationString.slice(0, 2);
    const stringYear = expirationString.slice(2, 4);
    return { cardString, stringMonth, stringYear };
  } 
  // 剩下的就是IBlinkCardScanResults类型,做对应处理
  else {
    const { cardNumber, expiryDate } = results;
    return {
      cardString: cardNumber,
      stringMonth: String(expiryDate.month).padStart(2, '0'),
      stringYear: String(expiryDate.year).slice(-2)
    };
  }
};

方案3:使用类型断言(不推荐)

如果你确定当前场景下绝对不会传入IBlinkCardScanResults类型的结果,可以用类型断言绕过校验:

<ScanForm 
  onSubmit={onSubmit} 
  parseScanResults={parseScanResults as (results: IBlinkCardScanResults | IVoucherScanResults) => IParsedScanResults}
>
  {/* 子组件内容 */}
</ScanForm>

该方案绕过了TypeScript的类型检查,后续如果传入不符合预期的参数可能会引发运行时错误,仅建议临时调试时使用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.16 09:15:04