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

如何利用TypeScript泛型实现React输入组件onChange类型收窄?

可以实现,以下是修正方案

原代码的核心问题是:泛型参数TypeT在函数内部做类型判断时,TypeScript没法把宽泛的泛型约束收窄到具体的"number"或其他类型,导致调用onChange时出现类型不兼容的报错。

方案一:用联合类型定义Props(推荐)

直接把InputProps定义成包含不同type对应不同onChange参数的联合类型,让TypeScript自动完成类型收窄:

import React, { ChangeEvent } from 'react'

type InputProps = 
  | { type: 'number'; onChange: (value: number) => void }
  | { type: Exclude<React.HTMLInputTypeAttribute, 'number'>; onChange: (value: string) => void }

function Input({ type, onChange }: InputProps) {
  const handleChange = (event: ChangeEvent<HTMLInputElement>) => {
    if (type === 'number') {
      onChange(event.currentTarget.valueAsNumber)
    } else {
      onChange(event.currentTarget.value)
    }
  }

  return <input type={type} onChange={handleChange} />
}

// 使用示例
<>
  Valid text:
  <Input type="text" onChange={(value) => console.log(value)} /> {/* value自动推断为string */}
  Valid number:
  <Input type="number" onChange={(value) => console.log(value)} /> {/* value自动推断为number */}
  Invalid:
  <Input type="text" onChange={(value: number) => console.log(value)} /> {/* 直接触发TS报错,符合预期 */}
</>

方案二:泛型结合类型断言(适合需保留泛型的场景)

如果必须保留泛型写法,可以在调用onChange时添加类型断言,同时通过泛型约束保证类型对应:

import React, { ChangeEvent, HTMLInputTypeAttribute } from 'react'

export type InputProps<TypeT extends HTMLInputTypeAttribute> = {
  type: TypeT,
  onChange: (value: TypeT extends 'number' ? number : string) => void
}

function Input<TypeT extends HTMLInputTypeAttribute>({ type, onChange }: InputProps<TypeT>) {
  const handleChange = (event: ChangeEvent<HTMLInputElement>) => {
    if (type === 'number') {
      onChange(event.currentTarget.valueAsNumber as TypeT extends 'number' ? number : string)
    } else {
      onChange(event.currentTarget.value as TypeT extends 'number' ? number : string)
    }
  }

  return <input type={type} onChange={handleChange} />
}

// 使用示例同前,类型推断依然生效

补充说明

  • 方案一的联合类型写法更直观,不需要额外的类型断言,TypeScript能完美完成类型收窄,是更推荐的实现方式。
  • 两种方案都能实现需求:当type为"number"时,onChange的参数自动匹配number类型;其他type时参数为string类型,错误的类型传入会直接触发TypeScript报错。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 12:42:17