Adjusting the return type based on the relationships defined in a Prisma object

Is there a way to implement a function that takes a Prisma object and dynamically sets the return type based on the included relations?

I am aiming to type versionWithRelations with properties like pages, variables, and actions, while versionWithoutRelations should not have those properties.

Below is my initial approach:

import { Prisma } from "@prisma/client";

const getVersion = <
  Relations extends Prisma.AppVersionInclude,
  App extends Prisma.AppGetPayload<{
    include: { versions: { include: Relations } };
  }>,
>(
  app: App,
): Prisma.AppVersionGetPayload<{ include: Relations }> => {
  return app.versions[0]!;
};

const withRelations = await prisma.app.findUnique({
  where: { id: "foo" },
  include: {
    versions: {
      include: {
        pages: true,
        variables: true,
        actions: true,
      },
    },
  },
});

const withoutRelations = await prisma.app.findUnique({
  where: { id: "foo" },
  include: {
    versions: true,
  },
});
const versionWithRelations = getVersion(withRelations!);
const versionWithoutRelations = getVersion(withoutRelations!);

// Expected types:
// typeof versionWithRelations
type VersionWithRelations = {
  id: string;
  appId: string;
  majorVersion: number;
  minorVersion: number;
  patchVersion: number;
  pages: {
    id: string;
    appVersionId: string;
    path: string;
    description: string;
  }[];
  variables: {
    id: string;
    appVersionId: string;
    name: string;
    description: string;
  }[];
  actions: {
    id: string;
    appVersionId: string;
    name: string;
    description: string;
  }[];
}

// typeof versionWithoutRelations
type VersionWithoutRelations = {
  id: string;
  appId: string;
  majorVersion: number;
  minorVersion: number;
  patchVersion: number;
}

Here is my Prisma schema definition:


model App {
  id       String       @id @default(cuid())
  name     String
  versions AppVersion[]
}

model AppVersion {
  id           String        @id @default(cuid())
  appId        String
  majorVersion Int
  minorVersion Int
  patchVersion Int
  pages        AppPage[]
  variables    AppVariable[]
  actions      AppAction[]

  app App @relation(fields: [appId], references: [id], onDelete: Cascade)

  @@unique([appId, majorVersion, minorVersion, patchVersion])
}

model AppPage {
  id           String @id @default(cuid())
  appVersionId String
  path         String
  description  String

  appVersion AppVersion @relation(fields: [appVersionId], references: [id], onDelete: Cascade)

  @@unique([appVersionId, path])
}

model AppVariable {
  id           String @id @default(cuid())
  appVersionId String
  name         String
  description  String

  appVersion AppVersion @relation(fields: [appVersionId], references: [id], onDelete: Cascade)

  @@unique([appVersionId, name])
}

model AppAction {
  id           String @id @default(cuid())
  appVersionId String
  name         String
  description  String

  appVersion AppVersion @relation(fields: [appVersionId], references: [id], onDelete: Cascade)

  @@unique([appVersionId, name])
}

Answer №1

If my interpretation is correct, you are searching for AppVersion entries with a matching appId value. Have you considered utilizing prisma.appVersion.findMany with the specific appId you are looking for?

const versionWithRelations = await prisma.appVersion.findMany({
  include: {
    pages: true,
    variables: true,
    actions: true,
  },
  where: {
    appId: "bar"
  }
});

const versionWithoutRelations = await prisma.appVersion.findMany({
  where: {
    appId: "bar"
  }
});

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

What is the way to send custom properties to TypeScript in combination with StyledComponents?

Encountering an error while attempting to implement Styled Components 3 with TypeScript: TS2365: Operator '<' cannot be applied to types 'ThemedStyledFunction<{}, any, DetailedHTMLProps<TableHTMLAttributes<HTMLTableElement>, ...

Tips for modifying an axios instance during response interception

Is there a way to automatically update an axios instance with the latest token received in a response, without making a second request? The new token can be included in any response after any request, and I want to make sure that the last received token ...

Is the Inline Partial<T> object still throwing errors about a missing field?

I recently updated to TypeScript version ~3.1.6 and defined an interface called Shop as follows: export interface Shop { readonly displayName: string; name: string; city: string; } In this interface, the property displayName is set by the backend a ...

HTML template failing to retrieve data from Angular dataSource

My goal is to import data from an Excel file into my angular application. I have successfully retrieved the data from the Excel file, parsed it to extract the necessary columns, and stored it in an array within my service.ts file. I call the service from ...

Taking advantage of Input decorator to access several properties in Angular 2

I am currently working on a component that is designed to receive two inputs through its selector. However, I would like to make it flexible enough to accept any number of inputs from various components. Initially, I tried using a single @Input() decorator ...

Tips for sorting server components using a URL search parameter [Next.js, Prisma]

My goal is straightforward: I want to be able to filter my Prisma database based on parameters passed in the URL when I click on a CategoryBox. After clicking on a CategoryBox, my URL does change to something like http://localhost:3000/?category=XYZ, but ...

Guide on triggering a bootstrap popup modal using a TypeScript file

I am currently working on an Angular project where I need to launch a popup modal when my function is called. I came across an example on w3schools, but it only contains the HTML logic to open the popup. What I want to achieve is to open the popup from th ...

Here's a revised version: "How to link a lambda layer with a function in a serverless.ts file using the

When working with the serverless framework using the typescript template, a serverless.ts file is generated. I am currently integrating lambda layers with existing functions and encountering a typescript error. The error message reads: "Type '{ Ref: ...

The object is classified as 'undetermined' (2571) upon implementation of map() function

Despite conducting a thorough search about this error online, I still haven't been able to find a solution. Let's jump into an example with data that looks like this: const earthData = { distanceFromSun: 149280000, continents: { asia: {a ...

Switching cell icon when clicked - A step-by-step guide

I have a situation in ag-grid where I need to update the icon of a button in a cell when it is clicked to indicate progress and then revert back to its original state upon completion of the action. Below is the code snippet: my-custom.component.ts < ...

Encountering the "Unrecognized teardown 1" error when subscribing to an Observable in Typescript and Angular2

Having trouble with using an Observable in my Angular2.rc.4 Typescript app. Check out the plunker for it here: https://embed.plnkr.co/UjcdCmN6hSkdKt27ezyI/ The issue revolves around a service that contains this code: private messageSender : Observable< ...

Integrating Octokit middleware in Next.js for enhanced functionality

Currently, I am in the process of honing my skills by creating a GitHub app. In Octokit, there is a feature called createNodeMiddleware that caught my attention. However, integrating it with next.js seems to pose some challenges. My main issue right now re ...

Suggestions for efficiently filtering nested objects with multiple levels in RXJS within an Angular environment?

Just a Quick Query: Excuse me, I am new to Typescipt & RxJS. I have this JSON data: [ { "ID": "", "UEN": "", "Name": "", "Address": "", "Telephone&quo ...

Encountering parameter issues while working with Google Maps React in TypeScript

Currently, I'm utilizing TypeScript in this particular file. import React, {Component} from 'react' import {Map, InfoWindow, Marker, GoogleApiWrapper, mapEventHandler, markerEventHandler} from 'google-maps-react'; import { coordina ...

Question from a student: What is the best way to transfer information between different classes?

Currently, I am delving into SPFX development. My focus is on constructing a form that incorporates multiple classes in order to gain insight on how they can interact and share data among one another. In this scenario, I have established two distinct clas ...

Update your mappings for the city of Istanbul when utilizing both TypeScript and Babel

Currently, I am facing the challenge of generating code coverage for my TypeScript project using remap Istanbul. The issue arises due to the usage of async/await in my code, which TypeScript cannot transpile into ES5 directly. To circumvent this limitation ...

Steps for incorporating ProxyConfig in Angular7 Application1. First, create a new

Having trouble building the application with proxy configuration. It works fine with ng serve or npm run start, but I need it to work with npm run build or ng build. After that, I want to deploy the dist folder to Tomcat webapps and make everything functio ...

Encountering an error: "Unable to assign the 'id' property to an undefined object while attempting to retrieve it"

I'm running into an issue while attempting to retrieve a specific user from Firebase's Firestore. export class TaskService { tasksCollection: AngularFirestoreCollection<Task>; taskDoc: AngularFirestoreDocument<Task>; tasks: Obs ...

"Functioning seamlessly in Chrome, yet encountering compatibility issues in Firefox - the

ERRORS ENCOUNTERED IN FIREFOX: ReferenceError: reference to undefined property G.search es6-shim.min.js:10:7752 ReferenceError: reference to undefined property G[e] es6-shim.min.js:10:1 mutating the [[Prototype]] of an object will cause your code to run v ...

Instructions for including a class are ineffective

I am trying to dynamically add a class to a div based on two conditions. To achieve this, I have created a custom directive as shown below: import { Directive, HostBinding, Input } from '@angular/core'; @Directive({ selector: '[confirmdia ...