Reputation: 1200
I'm not sure why I'm getting this error. Type 'any[]' is not assignable to type 'never[]'. TS2345
Here is my code. It's complaining about the merged array.
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();
}, []);
This is the line returning the error -
setAllInfo(merged);
I've tried
const result : string[] = [];
As well as const
[allInfo, setAllInfo] = useState([] as any);
Upvotes: 1
Views: 1342
Reputation: 1055
Giving your state an interface to strictly type it is a common pattern when using Typescript and React, otherwise the Typescript compiler will infer it. While with many other types inference will work, with an array most of the time it won't because the safest type to assume for an empty array is never[]
.
All of that to say that when you are creating an array that is assigned to a variable it is best to type that array strictly using an interface or custom type.
https://www.typescriptlang.org/docs/handbook/interfaces.html
So your code will often look more like this:
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();
}, []);
I typed that using what information I had, but in the future you should also give types to your API responses inside of fetchData
or you'll run into more type issues by relying on inference.
One last thing, fetchData
inside of the useEffect
is violating exhaustive-deps
linter rule React has. It isn't hugely problematic in this case, but fetchData
should really be defined inside the useEffect
or with the useCallback
hook.
Upvotes: 1
Reputation: 29
use default values this prevent future TypeError, try to use real typed, not use any like type
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();
}, []);
`
Upvotes: 0
Reputation: 4214
You can fix the error be giving merged
a better type than the inferred one (never[]
).
const merged: any[] = [];
should be enough, but I would recommend you consider a better type.
You can also help typescript infer the type by using the Array.prototype.map
method, and it's generally better to use .map
when you want to create new array with every element transformed from the original array.
const merged = validatorResponse.data.results.map((result, i) => ({
...result,
...resultBatch.data[i],
})
Upvotes: 0