as the title says, I have a comprehension problem with the use of Typescript, laravel and vue. Following case: I have a parent and a child component. With the parent component I make a get request to my controller which requests weather data from an external api. When they are received I validate them in the controller for the correct type safety and then give them as props to my parent component. In the parent component I also want to check these props for type safety and have given Data the type of my interface. If I now create a dummy array in the controller and change e.g. the name of the city into a number and send this dummy array to my parent component, it is not recognized as a number. Am I doing something wrong or have I configured something wrong?
Parent component:
<script lang="ts" setup>
import { defineProps, reactive, ref, onMounted } from 'vue';
import WeatherDisplay from '@/Pages/WeatherDisplay.vue';
import type { Refs,WeatherData } from "@/interfaces/interfaces";
import { useDark, useToggle } from '@vueuse/core';
import { router } from '@inertiajs/vue3';
const isDark = useDark();
const toggleDark = useToggle(isDark);
// Define the props for the component as a type-based declaration
const props = defineProps<{
data: WeatherData
}>
();
// This object contains all required refs
const allRefs = ref<Refs>({
searchWeather: '',
errorMessage: '',
}
);
// Creates a reactive array that is updated with weatherData
const weatherData = reactive<WeatherData[]>([
]);
// Function to load data from local storage
function loadDataFromLocalStorage(): WeatherData[] {
const data = localStorage.getItem('weatherData');
return data ? JSON.parse(data) : [];
}
// Function to set data to local storage
function setDataToLocalStorage(data: WeatherData[]) {
console.log(weatherData);
localStorage.setItem('weatherData', JSON.stringify(data));
}
// Delete weather data from array and local storage
function deleteWeatherData(index: number) {
weatherData.splice(index, 1);
localStorage.setItem('weatherData', JSON.stringify(weatherData));
}
// Load the data from local storage on mounted
onMounted(() => {
const savedData = loadDataFromLocalStorage();
if (savedData.length > 0) {
weatherData.splice(0, weatherData.length, ...savedData);
}
if (props.data && !props.data.error) {
weatherData.push(props.data);
setDataToLocalStorage(weatherData);
} else if (props.data && props.data.error) {
allRefs.value.errorMessage = props.data.error.message;
console.log(allRefs.value.errorMessage);
}
});
// Define a method to send the GET request to the backend
async function submit() {
try {
await router.get('/weather', { searchWeather: allRefs.value.searchWeather });
} catch (error) {
console.log(error);
}
}
</script>
Controller:
<?php
declare(strict_types=1);
namespace App\Http\Controllers;
use App\Classes\ApiErrorCodes;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Http;
use Inertia\Inertia;
use Illuminate\Support\Facades\Validator;
class GetWeather extends Controller
{
public function fetchWeather(Request $request): object
{
$city = $request->input('searchWeather');
$key = config('services.weather.key');
$response = Http::get(
url: "https://api.weatherapi.com/v1/forecast.json",
query: [
'key' => $key,
'q' => $city,
'days' => 3,
'aqi' => 'no',
'alerts' => 'no',
'lang' => 'de',
]
);
// Decode the JSON content of the HTTP response into a PHP array
$data = json_decode($response->body(), true);
// Checks the array for type declaration
$validator = Validator::make($data, [
'current.cloud' => 'integer',
'current.condition.text' => 'string',
'current.condition.icon' => 'string',
'current.is_day' => 'integer',
'current.last_updated_epoch' => 'integer',
'current.temp_c' => 'numeric',
'current.uv' => 'numeric',
'current.wind_kph' => 'numeric',
'forecast.forecastday' => 'array',
'location.country' => 'string',
'location.lat' => 'numeric',
'location.localtime' => 'string',
'location.localtime_epoch' => 'integer',
'location.lon' => 'numeric',
'location.name' => 'string',
'location.region' => 'string',
'location.tz_id' => 'string',
]);
// Check if there is an error code in the JSON response
if (isset($data['error']) && isset($data['error']['code'])) {
// Extract error code from JSON response
$errorCode = $data['error']['code'];
// Define array of valid error codes
$validErrorCodes = [
ApiErrorCodes::CODE_API_KEY_INVALID,
ApiErrorCodes::CODE_API_KEY_DISABLED,
ApiErrorCodes::CODE_NO_MATCHING_LOCATION,
ApiErrorCodes::CODE_PARAMETER_MISSING
];
// Check if the error code is included in the list of valid error codes
if (in_array($errorCode, $validErrorCodes)) {
// Fehlermeldung in der JSON-Antwort aktualisieren
$data['error']['message'] = ApiErrorCodes::getMessage($errorCode);
}
}
// Checks if an error occurred during validation
if ($validator->fails()) {
// Validation error
return response()->json(['error' => $validator->errors()], 422);
}
//Calls the template and passes the object
return Inertia::render('Mainpage', ['data' => $data]);
}
}
Interface:
export interface WeatherData {
error: {
message: string;
};
current: {
cloud: number;
condition: {
text: string;
icon: string;
};
is_day: number;
last_updated_epoch: number;
temp_c: number;
uv: number;
wind_kph: number;
};
forecast: {
forecastday: {
date: string;
day: {
maxtemp_c: number;
daily_chance_of_rain: number;
condition: {
text: string;
icon: string;
};
};
}[];
};
location: {
country: string;
lat: number;
localtime: string;
localtime_epoch: number;
lon: number;
name: number;
region: string;
tz_id: string;
};
}