Получение ошибки машинописного текста: тип ‘any[]’ не может быть присвоен типу ‘never[]’. TS2345

#javascript #reactjs #typescript

#javascript #reactjs #typescript

Вопрос:

Я не уверен, почему я получаю эту ошибку. Type 'any[]' is not assignable to type 'never[]'. TS2345 Вот мой код. Он жалуется на объединенный массив.

   const [allInfo, setAllInfo] = useState([]);

  useEffect(() => {
    async function fetchData() {
      const validatorResponse = await axios.get(validatorEndpoint);
      const validatorIps = [];
      for (let i = 0; i < validatorResponse.data.count; i  = 1) {
        const ipAddress = validatorResponse.data.results[i].ip_address;
        validatorIps.push({query: ipAddress});
      }
      const resultBatch = await axios.post(ipInfoEndpoint, validatorIps);
      const merged = [];
      for (let i = 0; i < validatorResponse.data.results.length; i  = 1) {
        merged.push({
          ...validatorResponse.data.results[i],
          ...resultBatch.data[i],
        });
      }
      console.log(merged);
      setAllInfo(merged);
    }
    fetchData();
  }, []);
 

Это строка, возвращающая ошибку —

 setAllInfo(merged);
 

Я уже пробовал

 const result : string[] = [];
 

А также const

 [allInfo, setAllInfo] = useState([] as any);
 

Комментарии:

1. Вы пробовали const [allInfo, setAllInfo] = useState<any[]>([]); ?

2. @JayKariesch Только что попробовал это и получил, что тип «любой» не может быть присвоен типу «никогда»

3. Вы говорите, что он жалуется на объединенный массив, вы имеете в виду, когда вы пытаетесь установить объединенный массив в состояние или другую строку кода?

4. @CoryHarper Да, когда я пытаюсь setAllInfo(объединенный); Это строка, возвращающая ошибку

5. Какие типы для validatorResponse.data.results[i] и resultBatch.data[i] ? Если какой-либо из них есть never , результирующие выражения должны merged быть never[] .

Ответ №1:

Предоставление вашему состоянию интерфейса для строгого ввода является обычным шаблоном при использовании Typescript и React, в противном случае компилятор Typescript выведет это. В то время как со многими другими типами вывод будет работать, с массивом в большинстве случаев это не так, потому что самый безопасный тип, который можно использовать для пустого массива never[] .

Все это говорит о том, что когда вы создаете массив, который присваивается переменной, лучше всего вводить этот массив строго с использованием интерфейса или пользовательского типа.

https://www.typescriptlang.org/docs/handbook/interfaces.html

Таким образом, ваш код часто будет выглядеть примерно так:

 interface Foo {
  ...
}
...

const [allInfo, setAllInfo] = useState<Foo[]>([]);

const fetchData = async (): Promise<void> => {
  const { 
    data: {
     results = []
    } = {} 
  } = await axios.get(validatorEndpoint);
  const validatorIps = results.map(({ ip_address }) => ({query: id_address}));
  const { data = [] } = await axios.post(ipInfoEndpoint, validatorIps);

  const merged = results.map((result, i) => ({
    ...result,
    ...data[i]
  });

 setAllInfo(merged)
}

useEffect(() => {
  fetchData();
}, []);
 

Я ввел это, используя ту информацию, которая у меня была, но в будущем вам также следует указывать типы для ваших ответов API внутри fetchData , иначе вы столкнетесь с большим количеством проблем с типами, полагаясь на вывод.

И последнее, fetchData внутри useEffect React нарушает exhaustive-deps правило linter. В этом случае это не очень проблематично, но fetchData действительно должно быть определено внутри useEffect или с useCallback помощью хука.

Ответ №2:

Вы можете исправить ошибку, указав merged лучший тип, чем предполагаемый ( never[] ) .

const merged: any[] = []; должно быть достаточно, но я бы рекомендовал вам выбрать лучший тип.

Вы также можете помочь typescript определить тип с помощью Array.prototype.map метода, и его обычно лучше использовать .map , когда вы хотите создать новый массив с каждым элементом, преобразованным из исходного массива.

 const merged = validatorResponse.data.results.map((result, i) => ({
   ...result,
   ...resultBatch.data[i],
})
 

Ответ №3:

используйте значения по умолчанию, чтобы предотвратить будущую ошибку типа, попробуйте использовать real typed, а не использовать какой-либо подобный тип

 const [allInfo, setAllInfo] = useState<Array<typed>>([]);

const fetchData = async (): Promise<void> => {
  const { 
    data: {
     results = []
    } = {} 
  } = await axios.get(validatorEndpoint);
  const validatorIps = results.map(({ ip_address}) => ({query: id_address}));

  const { data = []}= await axios.post(ipInfoEndpoint, validatorIps);
  const merged = results.map((result, i) => ({
    ...result,
    ...data[i]
  });
 setAllInfo(merged)
}

useEffect(() => {
  fetchData();
}, []);
 

`