首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >TS:解构包含对象和函数(setter)的数组只适用于@ts-忽略

TS:解构包含对象和函数(setter)的数组只适用于@ts-忽略
EN

Stack Overflow用户
提问于 2020-07-24 12:49:57
回答 3查看 358关注 0票数 3

我有一个React钩子,用于设置上下文提供程序的值。

代码语言:javascript
复制
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告诉我返回类型如下:

代码语言:javascript
复制
(alias) useAuth(): (React.Dispatch<React.SetStateAction<boolean>> | {
    token: string;
    isLoading: boolean;
})[]

因为我不知道如何描述类型,所以我使用了以下方法:

代码语言:javascript
复制
export type inferredReturnType = ReturnType<typeof useAuth>;

我正在用下面的行初始化我的React上下文:

代码语言:javascript
复制
const AuthContext = React.createContext<inferredReturnType | undefined>(undefined);

但是,当我试图在组件中使用钩子时,如下所示:

代码语言:javascript
复制
const [{ token, isLoading }, setTryAuth] = useAuth();

我收到了错误信息

属性'token‘不存在于类型'Dispatch { token: string;isLoading: boolean;}'.ts(2339)上。

到目前为止,只有使用//@ts-忽略来抑制TSCompiler,才能使其工作。

在这里,上下文和上下文提供程序的代码:

代码语言:javascript
复制
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的结合,这扰乱了我的头脑,但我找不到一个好的文章/文档来阅读它。

谢谢你的帮忙!

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2020-07-24 13:14:02

TypeScript正在推断(A|B)[]类型(这是合理的,它不知道您总是要以相同的顺序返回东西),但是您需要元组类型[A, B]

你至少有两个选择:

显式定义类型

如下所示:

代码语言:javascript
复制
type UseAuthReturnType = [
    {token: string, isLoading: boolean},
    React.Dispatch<React.SetStateAction<boolean>>
];

如果你用这个,就像这样:

代码语言:javascript
复制
const useAuth = (): UseAuthReturnType => {
    // ...
};

...your破坏工程。

操场链接

使用as const

如下所示:

代码语言:javascript
复制
const useAuth = () => {
  // ...

  return [{ token, isLoading }, setTryAuth] as const;
};

操场链接

TypeScript将以不同的方式推断这一点。具体而言,它将推断:

代码语言:javascript
复制
readonly [
    {
        readonly token: string;
        readonly isLoading: boolean;
    },
    React.Dispatch<React.SetStateAction<boolean>>
]

假设您不希望将第一个条目作为实际对象接收并更改其值(我敢肯定您不愿意),那么通过推断,这也同样有效。

票数 2
EN

Stack Overflow用户

发布于 2020-07-24 13:25:17

类型记录推断返回类型,但在这种情况下,它做错了。

基本上,它看到一个由两个不同类型的对象组成的数组:

一种类型:

代码语言:javascript
复制
{
  token: string,
  isLoading: boolean
}

另一种类型:

代码语言:javascript
复制
React.Dispatch<React.SetStateAction<boolean>>

因此,类型记录决定返回类型是一个对象数组,这些对象要么是第一个类型,要么是第二个类型。,但它不知道它们是按照什么顺序返回的,或者数组到底有两个项。是您推断的类型:

代码语言:javascript
复制
({
  token: string,
  isLoading: boolean
} | React.Dispatch<React.SetStateAction<boolean>>)[]

这意味着:有一个可变数量的项,它们要么是一个react动作,要么是一个具有字符串token和布尔isLoading__的对象。

当您尝试使用它时,请调用:

代码语言:javascript
复制
const [{ token, isLoading }, setTryAuth] = useAuth();

打字本抱怨,因为从它的观点来看,有两个问题:

  1. 从数组中提取两个对象。类型记录没有推断数组的长度,因此他警告您,这两项可能不存在。
  2. 从第一个返回的项中提取密钥tokenisLoading。但是类型记录并不知道第一项具有该类型,因此它警告您,第一项可能是React.Dispatch<React.SetStateAction<boolean>>类型。

您可以通过对类型记录说返回类型正好有两个项来解决所有问题,并有一个特定的顺序:

代码语言:javascript
复制
type UseAuthReturnType = [
    {token: string, isLoading: boolean},
    React.Dispatch<React.SetStateAction<boolean>>
];

const useAuth = (): UseAuthReturnType => {
    // ...
};

现在类型记录知道,您总是有两个项,第一个项具有tokenisLoading键,第二个项是react操作。

票数 1
EN

Stack Overflow用户

发布于 2020-07-24 13:14:14

useAuth被键入以返回一个包含这两种类型的数组。例如React.Dispatch<React.SetStateAction<boolean>>{token: string; isLoading: boolean;},错误告诉您不能将属性分配给属性token,因为它不是Dispatch.SetStateAction签名的一部分。

在我看来,这种类型的订单并不是强制执行的。也许可以在这个规则中提供帮助。

您可以筛选/键入来自useAuth的响应,这样类型就不再复杂了。如果总是使用tokenisLoading返回该类型,则更新该类型。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/63073917

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档