TypeScript无法自动推导React泛型组件类型问题求解
TypeScript无法自动推导泛型React组件类型的问题
我编写了如下泛型React组件:
export const QueryInputDropDown = <T extends unknown, I extends unknown>(props: { label: string; query?: (input?: I) => Promise<T[]>; queryInput: I | undefined; mapper?: (t: T) => Entity; selectedItem?: T | null; setSelectedItem?: (x: T | null) => void; }) => { ... }
使用该组件时,即便传入正确的数据类型,TypeScript(及我的IDE IntelliJ IDEA)仍报错,提示number|undefined无法赋值给I|undefined,或Entity|null无法赋值给T|null。
调用示例:
<QueryInputDropDown query={RpcMethods.getCompanyUsers} queryInput={company?.id} label={"Responsible"} selectedItem={resp} setSelectedItem={setResp} />
注:若手动指定类型则报错消失,示例如下:
<QueryInputDropDown<Entity, number> query={RpcMethods.getCompanyUsers} queryInput={company?.id} label={"Responsible"} selectedItem={resp} setSelectedItem={setResp} />
解决方案
问题根源在于TypeScript对可选属性的类型推导优先级较低,query作为可选属性,TS不会优先通过它推导T和I,反而会从queryInput、selectedItem等属性单独推导,导致类型不匹配。
1. 将query设为必填属性(推荐)
如果业务逻辑允许,把query改为必填,让TS优先通过它的函数签名推导T(返回数组的元素类型)和I(输入参数类型),再验证其他属性是否匹配:
export const QueryInputDropDown = <T, I>(props: { label: string; query: (input?: I) => Promise<T[]>; // 移除可选标记 queryInput?: I; mapper?: (t: T) => Entity; selectedItem?: T | null; setSelectedItem?: (x: T | null) => void; }) => { ... }
2. 调整属性顺序并简化类型定义
如果query必须保持可选,把它放在props的最前面引导TS优先处理,同时简化queryInput的类型定义(和query的输入参数保持一致):
export const QueryInputDropDown = <T, I>(props: { label: string; query?: (input?: I) => Promise<T[]>; queryInput?: I; mapper?: (t: T) => Entity; selectedItem?: T | null; setSelectedItem?: (x: T | null) => void; }) => { ... }
3. 检查依赖函数的类型定义
确认RpcMethods.getCompanyUsers的类型是否正确,确保它的输入为number | undefined、返回值为Promise<Entity[]>——只有依赖函数的类型明确,TS才能正确推导泛型。
4. 给泛型设置默认值(备选)
如果上述方法不适用,可以给泛型设置默认类型,减少手动指定的次数:
export const QueryInputDropDown = <T = Entity, I = number>(props: { label: string; query?: (input?: I) => Promise<T[]>; queryInput?: I; mapper?: (t: T) => Entity; selectedItem?: T | null; setSelectedItem?: (x: T | null) => void; }) => { ... }
内容的提问来源于stack exchange,提问作者Mahdi
相关产品推荐
相关产品推荐

