How to properly type models?
Dear,
I am trying to mock a server with MirageJS using Typescript, but I am not sure how to properly type the models and, unfortunately, Mirage docs does not say how to go about this.
To exemplify the problem, let's assume the following problem with relationships: say we have a given customer who can schedule an appointment at a given business. I tried to create the Models using the code below:
type Appointment = {
date: string;
status: string;
business: Business;
customer: Customer;
};
type Customer = {
name: string;
email: string;
phone: string;
appointments: Appointment[];
};
type Business = {
name: string;
image: string;
appointments: Appointment[];
customers: Customer[];
};
export function makeServer() {
const server = createServer({
models: {
appointment: Model.extend<Partial<Appointment>>({
customer: belongsTo(), // error here
business: belongsTo(), // error here
}),
customer: Model.extend<Partial<Customer>>({
apointments: hasMany("appointment"), // error here
}),
business: Model.extend<Partial<Business>>({
customers: hasMany("customer"), // error here
appointments: hasMany("appointment"), // error here
}),
},
// ...
but then, I get some errors saying (all errors are the same, so I will show here only the first one):
The expected type comes from property 'customer' which is declared here on type 'Partial<Appointment>'
If I change the type of the relations to any, then the error disappears. For example:
type Appointment = {
date: string;
status: string;
// business: Business;
// customer: Customer;
business: any;
customer: any;
};
But I'm not sure if that is the proper way to do so.
Does anyone know what I'm doing wrong? I believe Mirage docs would benefit from a more detailed explanation about typing Models.
Thank you!
Hi there, have you tried typing your models as Model.extend<Appointment>, without the Partial<>? You'll need to provide default values for any static properties.
Also, I find that I need to type my server config (the object passed to createServer() thus:
const serverConfig: ServerConfig<typeof models, typeof factories> = {
Where my models and factories have been defined and typed elsewhere, and ServerConfig is imported like:
import type { ServerConfig } from 'miragejs/server';
Typescript support was not baked into mirage from the start, and it's not 100% perfect, but I find that I'm usually able to accomplish what I need, aside from some more complex cases like traits.
Hi @IanVS,
Thank you very much for your quick reply. So apparently I need to change the way I'm creating the server. Would you have a sample public project in your GitHub (maybe you know about one) showing how to implement this? That would be super helpful.
Thank you once again! All the best
I'm sorry, I don't have anything open-source that I can share. And honestly, I don't have models that relate to each other in that way (everything refers only to other ids). I'd encourage you to explore creating models and factories with the correct types, and then typing the config object as I suggested above. And if you get stuck, feel free to reply here, or hop into ember's discord in the #ec-mirage channel.
Hi @IanVS,
Thank you very much for your quick reply. So apparently I need to change the way I'm creating the server. Would you have a sample public project in your GitHub (maybe you know about one) showing how to implement this? That would be super helpful.
Thank you once again! All the best
Hi @rfmiotto did you manage to solve this issue? Would love to see a code sample if possible please! 👍
Hi @jimsheen
Unfortunately no. I ended up removing the types from the models. I didn't want to spend too much time on mocking the server, so I took the easy way out.
But in case you have a solution, please let me know.
I'm sorry, I don't have anything open-source that I can share. And honestly, I don't have models that relate to each other in that way (everything refers only to other ids). I'd encourage you to explore creating models and factories with the correct types, and then typing the config object as I suggested above. And if you get stuck, feel free to reply here, or hop into ember's discord in the
#ec-miragechannel.
Hi @IanVS,
I would appreciate it if you could provide a code snippet doing what you mentioned here, I mean typing the ServerConfig for the case provided by @rfmiotto?
Thank you in advance!
Hi there, have you tried typing your models as
Model.extend<Appointment>, without thePartial<>? You'll need to provide default values for any static properties.Also, I find that I need to type my server config (the object passed to
createServer()thus:const serverConfig: ServerConfig<typeof models, typeof factories> = {Where my models and factories have been defined and typed elsewhere, and
ServerConfigis imported like:import type { ServerConfig } from 'miragejs/server';Typescript support was not baked into mirage from the start, and it's not 100% perfect, but I find that I'm usually able to accomplish what I need, aside from some more complex cases like traits.
I get that this is a very easy workaround, but it would also be very easy to change the types for mirage such that this is not needed
@GideonMax if you're willing to submit a PR, I'd be happy to review it!