I am writing an app which obtains weather data about a user’s location, and so far, everything works. However, when writing the code, I keep getting errors being highlighted, even though the code works.
Here is the code:
function array_to_comma_sep(array: Array<string>) {
let output: string = String();
for (let ele of array) {
output += ele + ",";
}
return output.substring(0, output.length-1);
}
class Feature {
name: string;
unit: string;
constructor(name: string, unit: string) {
this.name = name;
this.unit = unit;
}
}
type GeoLocation = {
latitude: number;
longitude: number;
}
async function getWeatherData() {
const HOURLY_FEATURES: Array<Feature> = [
new Feature("temperature_2m", "celsius"),
new Feature("relativehumidity_2m", "%"),
new Feature("apparent_temperature", "celsius"),
new Feature("precipitation_probability", "%"),
new Feature("precipitation", "mm"),
new Feature("snow_depth", "m"),
new Feature("visibility", "m")
]
// gets user's ip address
let ip_address: string;
await $.getJSON("https://api.ipify.org?format=json", data => {
ip_address = data.ip;
});
// get user's location
let location: GeoLocation;
await $.get(`https://ipapi.co/${ip_address}/latlong/`, data => {
let [lat, long]: Array<number> = data.split(",").map((num: string) => { return parseFloat(num); });
location = {
latitude: lat,
longitude: long
}
});
// get information about the weather
let hourly_features = array_to_comma_sep(HOURLY_FEATURES.map((feat: Feature) => { return feat.name }));
await $.getJSON(`https://api.open-meteo.com/v1/forecast?latitude=${location.latitude}&longitude=${location.longitude}&hourly=${hourly_features}`, data => {
console.log(data);
})
}
getWeatherData();
The problematic parts arise due to VS Code’s syntax highlighting – it says that, in the line with await $.getJSON("https://api.ipify.org?format=json", data => {, I am the "Variable ‘ip_address’ is used before being assigned. ts(2454)`.
However, as aforementioned, in terms of performance, everything goes well. I can see my API response in the console as expected.
Does the TypeScript extension I have not realize that the value will be assigned later as the function is async, or am I doing something wrong? This is my first time using TypeScript.
Here is my HTML code as well.
<!DOCTYPE html>
<head>
<script crossorigin src="https://unpkg.com/react@18/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.0/jquery.min.js" integrity="sha512-3gJwYpMe3QewGELv8k/BX9vcqhryRdzRMxVfq6ngyWXwo03GFEzjsUm8Q7RZcHPHksttq7/GFoxjCVUjkjvPdw==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script src="app.tsx" type="text/babel"></script>
</head>
<body>
<div id="container"></div>
</body>
>Solution :
No, TypeScript does indeed not know when the callbacks are called, so it cannot infer that the variable will be initialised in time. But really you just shouldn’t use callbacks at all – await returns the value that the promise fulfills with:
async function getWeatherData() {
const HOURLY_FEATURES = [
new Feature("temperature_2m", "celsius"),
new Feature("relativehumidity_2m", "%"),
new Feature("apparent_temperature", "celsius"),
new Feature("precipitation_probability", "%"),
new Feature("precipitation", "mm"),
new Feature("snow_depth", "m"),
new Feature("visibility", "m")
];
// gets user's ip address
const address: { ip: string } = await $.getJSON("https://api.ipify.org?format=json");
// get user's location
const geo_data: string = await $.get(`https://ipapi.co/${address.ip}/latlong/`);
const [lat, long] = geo_data.split(",").map(num => parseFloat(num));
const location: GeoLocation = {
latitude: lat,
longitude: long
};
// get information about the weather
const hourly_features = HOURLY_FEATURES.map(feat => feat.name).join(',');
const data = await $.getJSON(`https://api.open-meteo.com/v1/forecast?latitude=${location.latitude}&longitude=${location.longitude}&hourly=${hourly_features}`);
console.log(data);
}