Peter Kellner
08/03/2021, 7:34 PMXOR<UserSelect,null>.
That syntax means nothing to me. Is there some page that explains this syntax? I get from the example that somehow, it relates to where: {id: 1}... but I just don't see the connection and normally, I'm not the dumbest pencil in the box (so I had thought)Casey Graff
08/04/2021, 1:26 AMXOR
type?
If the former, that is a bit of a longer explanation, but I'd be happy to try my best.
If the later, that parameter is just saying that the select
field must be either equal to UserSelect
or to null
(mutually exclusive). Technically select
could also be undefined
because of the ?
.
In this particular case, I don't think use of XOR
is strictly required (you could use the |
instead), but there are other types like the data?: XOR<UserUpdateInput, UserUncheckedUpdateInput>
field in your screenshot where the mutual exclusivity between the two options is important.Casey Graff
08/04/2021, 1:27 AMXOR
type used in the index.d.ts file Prisma generates.
type Without<T, U> = { [P in Exclude<keyof T, keyof U>]?: never };
/**
* XOR is needed to have a real mutually exclusive union type
* <https://stackoverflow.com/questions/42123407/does-typescript-support-mutually-exclusive-types>
*/
type XOR<T, U> = (T | U) extends object ? (Without<T, U> & U) | (Without<U, T> & T) : T | U;
Peter Kellner
08/04/2021, 1:40 AMCasey Graff
08/04/2021, 1:44 AMUserSelect
type is determined by all of the fields you can select on the User model based on your Prisma schema.
So if you defined the following model in your schema.prisma file:
model User {
id Int @id @default(autoincrement())
name String
email String
nickname String?
}
The UserSelect type generated would look like:
type UserSelect = {
id?: boolean
name?: boolean
email?: boolean
nickname?: boolean
}
If you did some like the following:
const user = await prisma.user.findMany({
select: {
id: true
}
})
You would be fetching all Users in your database, but only selecting the id field on those users. So the resulting array would look like:
[{id: 1}, {id: 2}, ...]
Casey Graff
08/04/2021, 1:45 AMCasey Graff
08/04/2021, 1:47 AMinclude
functionality operates similar to select
, except that it returns all of the scalar fields plus any of the nested relations you want to fetch.
So in the second screenshot, the returned Users would have all of the scalar fields defined in the Prisma schema for a User + all of the Posts related to each User (with all of the Posts' scalar fields) + all of the Categories related to each of those Posts.Peter Kellner
08/04/2021, 1:47 AMCasey Graff
08/04/2021, 1:49 AMconst user = await prisma.user.findMany({
include: {
organization: {
select: {
name: true
}
}
}
})
To get all Users and all scalar fields on those Users + each User's organization, but only include the name of the organization (don't get any other fields of the organization).
In the absence of any include
or select
, Prisma will return all of the scalar fields on the model, but none of the nested relation's fields. It will however return the scalar field used to reference the relation (e.g. on User it might be an integer called organizationId
).Peter Kellner
08/04/2021, 1:54 AMCasey Graff
08/04/2021, 2:02 AMnode_modules/.prisma/client/index.d.ts
once you generate it. This file can get pretty large, but should be manageable to look through for a small project. I'd probably start by finding the type definition for the args accepted by a findUnique
or findMany
for one of your models.
You can then poke around there. Alternatively, if you have an editor with good autocomplete you could just start trying to write valid Prisma queries.
I'm not sure if there is a formal definition of the args everything accepts in the docs, but there is a consistent pattern that you can identify. I picked it up as I went and everything tended make sense once I got the hang of it.
For example, a findUnique
will always accept:
where
, select
, includes
, and rejectOnNotFound
The where
on a findUnique
will only accept any of the unique fields on your model.
The select
will accept any of the scalar fields on the model or any nested relations.
For scalars it will expect a boolean.
For nested one to one relations it will accept: select
, include
.
For nested one to many relations it will accept: select
, include
, where
, orderBy
, etc. (all of the fields a top-level findMany
would accept.
The include
would accepted any of the nested relations.
I found that I just started using Prisma and with a little bit of consulting the docs as I needed to use different parts + a lot of autocomplete and jumping to the type definition for my specific models I figured it out as I went.