I'm trying to get the typescript autocomplete to work with a function like this :
interface WeatherData {
coord: { lon: number; lat: number };
}
const fetchWeatherData = async (
location: string
): Promise<WeatherData | Error> => {
try {
const res = await axios.get(
`/weathr?q=${location}&APPID=${process.env.API_KEY}`
);
return res.data;
} catch (e) {
return new Error("Couldn't fetch weather data");
}
};
It will return the data If network request is successful otherwise an error with a custom message.
But autocomplete is completely disabled this way and I can't access any fields I defined in WeatherData
interface :
How can I use the autocomplete feature with typescript union type checking ?
The type WeatherData | Error
is not guaranteed to have any specific property, so you can't destructure it.
interface WeatherData {
coord: { lon: number; lat: number };
}
// Use `declare` to just work with the type of this function.
declare function fetchWeatherData(): WeatherData | Error
async function go() {
const { coord } = await fetchWeatherData()
}
This gives the type error:
Property 'coord' does not exist on type 'WeatherData | Error'.(2339)
This is because coord
is not a property that exists on Error
, so if an object of type Error
is returned, then you are accessing an invalid property.
The simple fix is narrow the type to make sure it's not an error before you access any non-error properties:
interface WeatherData {
coord: { lon: number; lat: number };
}
// Use `declare` to just work with the type of this function.
declare function fetchWeatherData(): WeatherData | Error
async function go() {
const result = await fetchWeatherData()
if (result instanceof Error) {
console.error('Failed to fetch weather', result)
} else {
console.log('geo location', result.coord.lat, result.coord.lon) // fine
}
}
Although, perhaps what you meant to do was to throw
an Error
, which interrupts the normal control flow. This would allow you to only return a WeatherData
since the code that handles the return value will be skipped if the error is raised.
interface WeatherData {
coord: { lon: number; lat: number };
}
function fetchWeatherData(): WeatherData {
if (Math.random() > 0.9) throw new Error('Failed to fetch weather')
return { coord: { lat: 123, lon: 45 }}
}
async function go() {
const { coord } = await fetchWeatherData() // fine
}