【问题标题】:typescript failed to infer destructuring array type in custom hook打字稿无法推断自定义挂钩中的解构数组类型
【发布时间】:2020-03-23 18:26:44
【问题描述】:
import * as React from "react";
import axios from "axios";
import {Fragment, useState, useEffect} from "react";
interface Ihits {
  objectID: string;
  url: string;
  title: string;
}

interface IinitialData<T> {
  hits: Array<T>
}

const useDataApi = (initialUrl:string, initialData: IinitialData<Ihits>) => {
  const [data, setData] = useState(initialData);
  const [url, setUrl] = useState(initialUrl);
  const [isLoading, setIsLoading] = useState(false);
  const [isError, setIsError] = useState(false);
  useEffect(() => {
    const fetchData = async () => {
      setIsError(false);
      setIsLoading(true);
      try {
        const result = await axios(url);
        setData(result.data);
      } catch (error) {
        setIsError(true);
      }
      setIsLoading(false);
    };
    fetchData();
  }, [url]);
  // return [{ data, isLoading, isError }, setUrl];
  return [{data, isLoading, isError }, setUrl];
};

const UseDataFetch: React.FC = () => {
  const [query, setQuery] = useState('redux');
  **const [{data, isLoading, isError}, setUrl] = useDataApi(**
    'https://hn.algolia.com/api/v1/search?query=redux',
    { hits: [] },
  );
  return (
    <Fragment>
      <form
        onSubmit={event => {
          **setUrl(**
            `http://hn.algolia.com/api/v1/search?query=${query}`,
          );
          event.preventDefault();
        }}
      >
        <input
          type="text"
          value={query}
          onChange={event => setQuery(event.target.value)}
        />
        <button type="submit">Search</button>
      </form>
      {isError && <div>Something went wrong ...</div>}
      {isLoading ? (
        <div>Loading ...</div>
      ) : (
        <ul>
          {data.hits.map((item: Ihits) => (
            <li key={item.objectID}>
              <a href={item.url}>{item.title}</a>
            </li>
          ))}
        </ul>
      )}
    </Fragment>
  );
}
export default UseDataFetch;

我研究了这个链接https://www.robinwieruch.de/react-hooks-fetch-data的例子

我尝试了各种解决方案,但根本无法设置类型化解构值。除了使用任何类型和对象返回(例如:return {data, isLoading, isError, setUrl};)

很感激有人能告诉我错过了什么

【问题讨论】:

  • TS 是否抛出错误?
  • @azium 在文本编辑器中抛出 ts 错误

标签: javascript reactjs typescript type-inference destructuring


【解决方案1】:

Typescript 无法推断它,因为您返回的数组中每个元素的类型都不同。从 Typescript 的角度来看,如果您不明确键入,它就无法将它们关联起来。

return [{data, isLoading, isError}, setUrl];

第一种方法是显式定义 useDataApi 方法的返回类型:

const useDataApi = (initialUrl:string, initialData: IinitialData<Ihits>): 
[{data: IinitialData; isLoading: boolean; isError: boolean}, string] => {
// your code here
}

其他方法是返回特定类型的对象而不是数组。 您可以定义自定义类型:

type DataApiResponse = {
  response: {
    data: IinitialData<Ihits>;
    isLoading: boolean;
    isError: boolean;
  };
  setUrl: Dispatch<SetStateAction<string>>;
}

然后将其用作:

return {response: {data, isLoading, isError}, setUrl} as DataApiResponse;

最后修改UseDataFetch方法:

const {response, setUrl} = useDataApi(
  "https://hn.algolia.com/api/v1/search?query=redux",
  { hits: [] }
);

const {data, isError, isLoading} = response;

【讨论】:

  • 很好地解释了为什么它不能推断出类型。创建一个特定的类型别名总是好的,但即使你只是将返回类型更改为一个对象(并对结果进行解构),TS 也应该能够比数组更好地推断出来。
【解决方案2】:

或者只是将as const 添加到自定义挂钩的返回参数中。

return [whatever, whatEver] as const

【讨论】:

    【解决方案3】:

    如果 TypeScript 无法推断它,那么您可以自己显式声明函数的返回类型:

    // Note return type added after ':'
    const useDataApi = (initialUrl:string, initialData: IinitialData<Ihits>): [{data: IinitialData; isLoading: boolean; isError: boolean}, string] => {
      const [data, setData] = useState(initialData);
      const [url, setUrl] = useState(initialUrl);
      const [isLoading, setIsLoading] = useState(false);
      const [isError, setIsError] = useState(false);
      useEffect(() => {
        const fetchData = async () => {
          setIsError(false);
          setIsLoading(true);
          try {
            const result = await axios(url);
            setData(result.data);
          } catch (error) {
            setIsError(true);
          }
          setIsLoading(false);
        };
        fetchData();
      }, [url]);
      // return [{ data, isLoading, isError }, setUrl];
      return [{data, isLoading, isError }, setUrl];
    };
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-08-12
      • 2018-03-15
      • 1970-01-01
      • 2018-06-09
      • 2022-01-16
      • 2015-03-23
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多