#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();
}, []);
`