带条件泛型的自定义类型在useState中触发TS错误的原因与解决
TypeScript泛型类型使用问题排查与解决
问题场景
定义了如下泛型类型:
export type MutationResponse<T = never> = { status: number; message: string | null; } & (T extends never ? {} : { data: T });
当省略泛型参数直接使用时出现错误:
const [response, setResponse] = useState<MutationResponse>({ status: 0, message: "" });
错误信息
Object literal may only specify known properties, and 'status' does not exist in type '() => never'
补充说明
显式指定泛型参数时使用完全正常:
const [response, setResponse] = useState<MutationResponse<string>>({ status: 0, message: "", data: "" });
原因分析
直接写MutationResponse而不指定泛型参数时,TypeScript不会自动用默认值never实例化这个泛型类型,而是把它当成了泛型类型构造器本身(即需要传入泛型参数才能生成具体类型的“模板”)。而useState的泛型参数要求传入具体类型,不是模板,此时TypeScript会把未指定泛型的MutationResponse误解析成返回never的函数类型,自然会提示对象里的status属性不存在。
解决方法
方法1:显式指定默认泛型参数
直接传入默认的never来实例化类型:
const [response, setResponse] = useState<MutationResponse<never>>({ status: 0, message: "" });
方法2:创建无泛型的别名
给默认实例化的类型单独起一个别名,方便后续直接使用:
export type MutationResponse<T = never> = { status: number; message: string | null; } & (T extends never ? {} : { data: T }); // 定义对应默认never情况的别名 export type EmptyMutationResponse = MutationResponse<never>;
使用时直接调用别名:
const [response, setResponse] = useState<EmptyMutationResponse>({ status: 0, message: "" });
内容的提问来源于stack exchange,提问作者FutureCake
相关产品推荐
相关产品推荐

