Computed fields
Computed fields allow you to derive a new field based on existing data. A common example is when you compute a full name from a first and last name. In your database, you may only store the first and last name, but you can define a function that computes a full name by combining the first and last name. This field is read-only and stored in your application's memory, not in your database.
Deriving a Full Name from a First and Last Name
Prisma Client does not yet natively support computed fields, but with a bit of TypeScript magic, you can define a function that accepts a generic as an input then extend that generic to ensure it conforms to a specific structure. Finally, you can return that generic with additional computed fields. Let's see how that might look:
// Define a type that needs a first and last nametype FirstLastName = {firstName: stringlastName: string}// Extend the T generic with the fullName attributetype WithFullName<T> = T & {fullName: string}// Take objects that satisfy FirstLastName and computes a full namefunction computeFullName<User extends FirstLastName>(user: User): WithFullName<User> {return {...user,fullName: user.firstName + ' ' + user.lastName,}}async function main() {const user = await prisma.user.findUnique({ where: 1 })const userWithFullName = computeFullName(user)}
In the TypeScript example above, a User
generic has been defined that extends the FirstLastName
type. This means that whatever you pass into computeFullName
must contain firstName
and lastName
keys.
A WithFullName<User>
return type has also been defined, which takes whatever User
is and tacks on a fullName
string attribute.
With this function, any object that contains firstName
and lastName
keys can compute a fullName
. Pretty neat, right?
Going Further
- Learn how you can move the
computeFullName
function into a custom model. - There's an outstanding feature request to add native support to Prisma Client. If you'd like to see that happen, make sure to upvote that issue and share your use case!