I am trying to use typescript for a Nuxt3 project and it is my first experience with Typescript.
I have this component that aims at creating or editing a person in the backend:
<template>
<UCard>
<template #header>
<h3 class="font-semibold text-xl">
{{
props.mode === "create"
? "Ajouter une personne"
: "Modifier une personne"
}}
</h3>
</template>
<UForm :schema="schema" :state="state" class="space-y-2" @submit="onSubmit">
<UFormGroup class="" label="Prénom" name="firstName">
<UInput v-model="state.firstName" :disabled="props.mode === 'update'" />
</UFormGroup>
<UFormGroup class="" label="Nom" name="lastName">
<UInput v-model="state.lastName" :disabled="props.mode === 'update'" />
</UFormGroup>
<UFormGroup class="" label="Email" name="email">
<UInput v-model="state.email" />
</UFormGroup>
<UFormGroup class="" label="Téléphone" name="phone">
<UInput v-model="state.phone" />
</UFormGroup>
<UFormGroup class="" label="Membre depuis" name="memberSince">
<UInput v-model="state.memberSince" type="date" />
</UFormGroup>
<UFormGroup class="" label="Membre l'an dernier?" name="memberLastYear">
<USelect v-model="state.memberLastYear" :options="mlyOptions" />
</UFormGroup>
<div class="inline-block flex-inline">
<UButton type="submit"> Enregistrer cette personne </UButton>
<UButton
color="gray"
variant="ghost"
icon="i-heroicons-x-mark-20-solid"
class="-my-1"
@click="$emit('close')"
/>
</div>
</UForm>
<template #footer> </template>
</UCard>
</template>
<script setup lang="ts">
import type { FormError, FormSubmitEvent } from "#ui/types";
import { z } from "zod";
import { usePersonsStore } from "@/stores/persons.js";
import { type IPerson } from "~/types/IPerson";
const props = defineProps({
mode: String,
person: { type: Object as () => IPerson },
});
const personsStore = usePersonsStore();
const emit = defineEmits(["close"]);
const mlyOptions = ["Oui", "Non"];
const schema = z.object({
firstName: z
.string()
.regex(
/^[ÈÉÊA-Z][a-zïèéê']*([\-\s]{1}[ÈÉÊA-Z]{1}[a-zïèéê]*)*$/,
"Capitale en début de chaque partie du prénom uniquement. Pas de double espace ou tiret. Pas d'espace ou de tiret en début et fin"
),
lastName: z
.string()
.regex(
/^([ÈÉÊA-Z]){1}('[ÈÉÊA-Z]+){0,1}[a-zïèéê']*([\-\s]{1}[ÈÉÊA-Z]{1}[a-z'ïèéê]*)*$/,
"Capitale en début de chaque partie du nom. Pas de double espace ou tiret. Pas d'espace ou de tiret en début et fin. Apostrophe des noms irlandais acceptée."
)
.toUpperCase(),
email: z.string().email("L'adresse électronique est mal formée"),
phone: z
.string()
.trim()
.transform((val, ctx) => {
val = val.replace(/\s/g, "");
if (val.length !== 10) {
ctx.addIssue({
code: z.ZodIssueCode.custom,
message: "You must enter 10 digits",
});
return z.NEVER;
}
var parts = val.match(/.{1,2}/g);
state.phone = parts.join(" ");
return state.phone;
}),
memberSince: z.coerce.date(),
memberLastYear: z.string(),
});
type Schema = z.output<typeof schema>;
const state: IPerson = reactive({
id: undefined,
firstName: "",
lastName: "",
email: "",
phone: "",
memberSince: "",
memberLastYear: "",
});
if (props.mode === "update") {
state.id = props.person.id;
state.firstName = props.person.firstName;
state.lastName = props.person.lastName;
state.email = props.person.email;
state.phone = props.person.phone;
state.memberSince = props.person.memberSince.substring(0, 10);
state.memberLastYear = props.person.memberLastYear;
}
async function onSubmit(event: FormSubmitEvent<any>) {
console.log("submit");
const { data, pending, error } = await useFetch("api/person", {
method: props.mode === "create" ? "POST" : "PUT",
body: event.data,
});
if (data) {
console.log("logging data with mode " + props.mode);
console.log(toRaw(data.value));
if (props.mode === "create") {
personsStore.addPerson(toRaw(data.value));
} else {
personsStore.updatePerson(toRaw(data.value));
}
}
if (error) {
console.log("logging error");
console.log(error.value);
}
emit("close");
}
</script>
Here is the IPerson
interface:
export interface IPerson {
id?: number;
firstName: string;
lastName: string;
email: string;
phone: string;
memberSince: string;
memberLastYear: string;
};
Before adding
typescript: {
typeCheck: true
}
to my nuxt.config.ts
, everything works fine.
But as soon as I add the typeCheck: true
, the compilation results in 9 errors, all related to the same thing which is
ERROR(vue-tsc) 'props.person' is possibly 'undefined'.
and that are in relation with all places where I use this props, mainly in this
if (props.mode === "update") {
state.id = props.person.id;
state.firstName = props.person.firstName;
state.lastName = props.person.lastName;
state.email = props.person.email;
state.phone = props.person.phone;
state.memberSince = props.person.memberSince.substring(0, 10);
state.memberLastYear = props.person.memberLastYear;
}
I have been searching the internet for hours never finding a solution. I need some help.
Finally providing a default value like this solved the problem