我有一个React钩子,用于设置上下文提供程序的值。
const useAuth = () => {
const [token, setToken] = useState("");
const [isLoading, setIsLoading] = useState(false);
const [tryAuth, setTryAuth] = useState(false);
useEffect(() => {
if (tryAuth) {
const getToken = async () => {
console.log("triggered");
setIsLoading(true);
const axiosInstance = axios.get<TokenResponseType>(
"http://localhost:3500/token"
);
const tokenResult = (await axiosInstance).data.accessToken;
setToken(tokenResult);
setIsLoading(false);
};
getToken();
}
}, [tryAuth]);
return [{ token, isLoading }, setTryAuth];
};
export default useAuth;
export type inferredType = ReturnType<typeof useAuth>;VSCode告诉我返回类型如下:

(alias) useAuth(): (React.Dispatch<React.SetStateAction<boolean>> | {
token: string;
isLoading: boolean;
})[]因为我不知道如何描述类型,所以我使用了以下方法:
export type inferredReturnType = ReturnType<typeof useAuth>;我正在用下面的行初始化我的React上下文:
const AuthContext = React.createContext<inferredReturnType | undefined>(undefined);但是,当我试图在组件中使用钩子时,如下所示:
const [{ token, isLoading }, setTryAuth] = useAuth();我收到了错误信息
属性'token‘不存在于类型'Dispatch { token: string;isLoading: boolean;}'.ts(2339)上。
到目前为止,只有使用//@ts-忽略来抑制TSCompiler,才能使其工作。
在这里,上下文和上下文提供程序的代码:
const AuthContext = React.createContext<inferredReturnType | undefined>(undefined);
const AuthContextProvider = (props: any) => {
//@ts-ignore
const [{ token, isLoading }, setTryAuth] = useAuth();
return (
<AuthContext.Provider value={[{ token, isLoading }, setTryAuth]}>
{props.children}
</AuthContext.Provider>
);
};
export default AuthContextProvider;
export const useAuthContext = () => {
//@ts-ignore
const [{ token, isLoading }, setTryAuth] = useContext(AuthContext);
if (token === undefined)
throw new Error('useAuthContext must be inside a Provider with a value');
return [{ token, isLoading }, setTryAuth];
};下面是代码沙箱的链接:
我试图实现的是在Robin的优秀博客文章中仅为TypeScript实现的“自定义数据获取钩子”。
我敢肯定,这是一些先进的类型,破坏了ES6和TypeScript的结合,这扰乱了我的头脑,但我找不到一个好的文章/文档来阅读它。
谢谢你的帮忙!
发布于 2020-07-24 13:14:02
TypeScript正在推断(A|B)[]类型(这是合理的,它不知道您总是要以相同的顺序返回东西),但是您需要元组类型[A, B]。
你至少有两个选择:
显式定义类型
如下所示:
type UseAuthReturnType = [
{token: string, isLoading: boolean},
React.Dispatch<React.SetStateAction<boolean>>
];如果你用这个,就像这样:
const useAuth = (): UseAuthReturnType => {
// ...
};...your破坏工程。
使用as const
如下所示:
const useAuth = () => {
// ...
return [{ token, isLoading }, setTryAuth] as const;
};TypeScript将以不同的方式推断这一点。具体而言,它将推断:
readonly [
{
readonly token: string;
readonly isLoading: boolean;
},
React.Dispatch<React.SetStateAction<boolean>>
]假设您不希望将第一个条目作为实际对象接收并更改其值(我敢肯定您不愿意),那么通过推断,这也同样有效。
发布于 2020-07-24 13:25:17
类型记录推断返回类型,但在这种情况下,它做错了。
基本上,它看到一个由两个不同类型的对象组成的数组:
一种类型:
{
token: string,
isLoading: boolean
}另一种类型:
React.Dispatch<React.SetStateAction<boolean>>因此,类型记录决定返回类型是一个对象数组,这些对象要么是第一个类型,要么是第二个类型。,但它不知道它们是按照什么顺序返回的,或者数组到底有两个项。是您推断的类型:
({
token: string,
isLoading: boolean
} | React.Dispatch<React.SetStateAction<boolean>>)[]这意味着:有一个可变数量的项,它们要么是一个react动作,要么是一个具有字符串token和布尔isLoading__的对象。
当您尝试使用它时,请调用:
const [{ token, isLoading }, setTryAuth] = useAuth();打字本抱怨,因为从它的观点来看,有两个问题:
token和isLoading。但是类型记录并不知道第一项具有该类型,因此它警告您,第一项可能是React.Dispatch<React.SetStateAction<boolean>>类型。您可以通过对类型记录说返回类型正好有两个项来解决所有问题,并有一个特定的顺序:
type UseAuthReturnType = [
{token: string, isLoading: boolean},
React.Dispatch<React.SetStateAction<boolean>>
];
const useAuth = (): UseAuthReturnType => {
// ...
};现在类型记录知道,您总是有两个项,第一个项具有token和isLoading键,第二个项是react操作。
发布于 2020-07-24 13:14:14
useAuth被键入以返回一个包含这两种类型的数组。例如React.Dispatch<React.SetStateAction<boolean>>或{token: string; isLoading: boolean;},错误告诉您不能将属性分配给属性token,因为它不是Dispatch.SetStateAction签名的一部分。
在我看来,这种类型的订单并不是强制执行的。也许可以在这个规则中提供帮助。
您可以筛选/键入来自useAuth的响应,这样类型就不再复杂了。如果总是使用token和isLoading返回该类型,则更新该类型。
https://stackoverflow.com/questions/63073917
复制相似问题