如何复用TypeScript自定义Hook的返回类型?
问题描述
我实现了如下自定义Hook:
export const useCreateAccount: UseCreateAccountOutputs = () => { ... return { error, loading, createAccount }; };
并定义了对应的类型:
type CreateAccountFn = () => Promise<void>; type UseCreateAccountOutputs = () => { loading: boolean; error: string | null; createAccount: CreateAccountFn; };
由于要创建多个类似的自定义Hook,不想重复定义loading: boolean;和error: string | null;这两个字段,于是定义了一个基础类型用于扩展:
export type CustomGraphqlHookOutputs = () => { loading: boolean; error: string | null; };
但尝试了两种写法都无法达到预期效果:
第一种写法:
type UseCreateAccountOutputs = CustomGraphqlHookOutputs & (() => { createAccount: CreateAccountFn; });
第二种写法:
type UseCreateAccountOutputs = () => { ...CustomGraphqlHookOutputs, createAccount: CreateAccountFn; };
请问这两种写法的问题出在哪里?
错误原因
核心问题是你把CustomGraphqlHookOutputs定义成了函数类型,但实际你需要复用的是函数返回的对象结构类型:
- 第一种写法里,交叉两个函数类型只会要求类型兼容(比如参数、返回值都要满足两个函数的要求),根本不会合并它们的返回值字段,所以完全达不到复用字段的目的。
- 第二种写法里,你试图在对象中展开一个函数类型,这是无效操作,TypeScript无法识别这种写法,自然会报错。
正确实现方式
先把基础类型改成函数返回的对象结构,而非函数类型:
// 只定义Hook返回对象中重复的字段结构 export type CustomGraphqlHookBaseResult = { loading: boolean; error: string | null; };
然后在定义Hook的输出类型时,让函数返回基础类型与自定义字段的组合:
type CreateAccountFn = () => Promise<void>; // 方式1:交叉类型 type UseCreateAccountOutputs = () => CustomGraphqlHookBaseResult & { createAccount: CreateAccountFn; }; // 方式2:对象扩展(与方式1效果一致) type UseCreateAccountOutputs = () => { ...CustomGraphqlHookBaseResult, createAccount: CreateAccountFn; };
这样修改后,所有需要loading和error字段的自定义Hook,都可以直接复用CustomGraphqlHookBaseResult类型,避免重复定义重复字段。
内容的提问来源于stack exchange,提问作者user8758206
相关产品推荐
相关产品推荐

