Show the Prisma model by utilizing the model's designated name

I am working on creating a function that displays a specific Prisma model based on the model name provided as a parameter. The challenge is to ensure that TypeScript can verify if the specified model actually exists each time.

/* 
file schema.prisma models:

model User {
  id          Int      @id @default(autoincrement())
  name        String
  password    String
  job         String   @default("")
  location    String   @default("")
  phone       String   @default("")
  email       String
}

model Participant {
  id         Int       @id @default(autoincrement())
  userID     Int
  groupID    Int
}

*/

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

function loadModel(modelName: /* string */) {
  const prisma = new PrismaClient();
  const Model = prisma[modelName]
}

loadModel("user")

An error occurs with the following code:

Element implicitly has an 'any' type because expression of type 'string' can't be used to index type 'PrismaClient<PrismaClientOptions, never, RejectOnNotFound | RejectPerOperation | undefined>'. No index signature with a parameter of type 'string' was found on type 'PrismaClient<PrismaClientOptions, never, RejectOnNotFound | RejectPerOperation | undefined>'.

To address this issue, I attempted adding : keyof PrismaClient to the modelName parameter. While this resolved the initial error, I encountered a new problem when trying to use functions like Model.create({...}):

Property 'create' does not exist on type '(<V extends "beforeExit">(eventType: V, callback: (event: V extends "query" ? QueryEvent : V extends "beforeExit" ? () => Promise : LogEvent) => void) => void) | ... 11 more ... | MessageDelegate<...>'. Property 'create' does not exist on type '<V extends "beforeExit">(eventType: V, callback: (event: V extends "query" ? QueryEvent : V extends "beforeExit" ? () => Promise : LogEvent) => void) => void'.

What steps should I take to resolve this issue?

Answer №2

The reason for the error is that modelName can be any string, but it should only be "user" or "participant" according to the schema.prisma model.

To retrieve a list of your models, you can use the Prisma type.

/* 
file schema.prisma models:

model User {
  id          Int      @id @default(autoincrement())
  name        String
  password    String
  job         String   @default("")
  location    String   @default("")
  phone       String   @default("")
  email       String
}

model Participant {
  id         Int       @id @default(autoincrement())
  userID     Int
  groupID    Int
}

*/

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

type PrismaOption = PrismaClient<
  Prisma.PrismaClientOptions,
  never,
  Prisma.RejectOnNotFound | Prisma.RejectPerOperation | undefined
>

// this will return "user" | "participant"
export type PrismaModel = keyof Omit<
  PrismaOption,
  | "$connect"
  | "$disconnect"
  | "$executeRaw"
  | "$executeRawUnsafe"
  | "$on"
  | "$queryRaw"
  | "$queryRawUnsafe"
  | "$transaction"
  | "$use"
>

function loadModel(modelName: PrismaModel) { // modelName type will be "user" | "participant"
  const prisma = new PrismaClient();
  return prisma[modelName]
}

loadModel("user")

Answer №3

If you want to access keys in the User type imported from @prisma/client, you can utilize the ts-transformer-keys library.

import { keys } from 'ts-transformer-keys';
import { User } from '@prisma/client'

const keysOfUser = keys<User>();

console.log(keysOfUser); // ['id', 'name', 'password', ...]

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

A guide to accessing parent attributes in Vue3 using typescript

Within my child component, I am facing an issue where I need to access the parent object but the commented lines are not functioning as expected. The structure of AccordionState is defined below: export type AccordionKeys = | "open" | "disa ...

Simply drag and drop the image from your browser window into the file input

Is there a way to drag an image from a browser window into a file input that I developed? Looking for assistance in creating an event that allows me to get the image when dragging it to an input. While I have successfully created an event to obtain the i ...

Challenges with Loading JSON Dynamically in Next.js using an NPM Package

In my TypeScript project, I have implemented a functionality where a json configuration file is dynamically loaded based on an enum value passed as a parameter to the getInstance function in my PlatformConfigurationFactory file. public static async getIn ...

Can you explain the purpose of FunctionConstructor in typeScript?

As I delved into the Typescript Ecmascript source code, I stumbled upon this intriguing snippet: interface FunctionConstructor { /** * Creates a new function. * @param args A list of arguments the function accepts. */ new(...args: st ...

Ways to conceal a button according to a particular trigger

On the page labeled standing-orders-details, I have configured it so that the display of the New Order button is hidden, but only if I first visit the new-order page. To begin, I need to ensure that the New Order button remains hidden on the standing-or ...

Angular - Issue: Unable to locate 'classlist.js'

require('classlist.js'); While building the project using Angular CLI, an error appeared in the console. I ran the command "npm install --save classlist.js" within the project directory. Error: Module not found: Can't resolve 'classl ...

Angular 5: Issues with retrieving response using HttpClient's get request

Alright, so typically I work with Angular 1.*, but I decided to dive into Angular 5 and man, it's been a bit of a challenge. It feels unnecessarily complex, but oh well... So I'm trying to make an HTTP call, and I have this node API that is retu ...

Having trouble extracting value from another component or dealing with an architectural issue?

Just recently delving into Angular, I embarked on this journey last week with a small programming foundation. My current project involves creating a simple blog application where I need to pass a value from the root (app.component.ts) to my component tag " ...

working with JSON arrays in angular framework

Is there a way to print a specific value from an array in typescript? Below is the code snippet in typescript that I'm working with: import { AngularFirestore } from '@angular/fire/firestore'; export class ProfileComponent implements OnInit ...

Challenges arise when working with multiple promises while attempting to retrieve download URLs from Cloud Storage

My goal is to save each downloadURL from multiple promises (files being uploaded) in an array while iterating through them. However, what's happening is that I only get the first output for every item, regardless of how many items I upload. It keeps g ...

Exploring StickIt: Binding the length property from a backbone.Collection

Exploring the use of Backbone, Marionette (1.8.3), StickIt, and TypeScript to effectively bind the length of a Backbone collection in real-time as items are added or removed. As someone new to StickIt, here's my current attempt: export class SomeVie ...

Reduce the use of if statements

Is there a way to optimize this function by reducing the number of if statements? The currentFeatures are determined by a slider in another file. The cost is updated if the currentFeatures do not match the previousFeatures, and if the user changes it back ...

PhpStorm flawlessly detects ES7 type hinting errors

For my project, I have implemented TypeScript. While JavaScript's array includes() function has been valid since ECMA6, setting the lib parameter in tsconfig to "es6" results in a non-fatal error being thrown in the browser console when using the foll ...

Conditional application of Angular animations is possible

After implementing the fadein effect from Angular-Animations in my ASP.NET based Angular project, I encountered an issue where only the first row is faded-in while the other rows are not displayed when using *ngIf. Here is a snippet of the code: <ng-te ...

binding data for an observable number in a loop

Is there a way to show stars for each item in a list using the 5-star scoring system on a video interface without creating an array for the score? interface Video{ Score: number; } <td> <span data-bind="foreach: score"> < ...

Converting a string into a component name (class name) in Angular 2

How can I convert the string "BoxOneComponent" into a class name BoxOneComponent in Angular 2? Is there a method similar to .toString() that allows for typecasting to a class name? ...

Is it possible for Typescript to automatically determine the exact sub-type of a tagged union by looking at a specific tag value?

I have an instance of type Foo, which contains a property bar: Bar. The structure of the Bar is as follows: type ABar = {name: 'A', aData: string}; type BBar = {name: 'B', bData: string}; type Bar = ABar | BBar; type BarName = Bar[&apos ...

What is the best way to indicate a particular element within a subdocument array has been altered in mongoose?

I have a specific structure in my Mongoose schema, shown as follows: let ChildSchema = new Schema({ name:String }); ChildSchema.pre('save', function(next){ if(this.isNew) /*this part works correctly upon creation*/; if(this.isModifi ...

Mapping fields in Angular collectively

I'm currently working on implementing a modal, and I'm looking to link values from the formBuilder to a specific property. Here's the snippet of code I'm working with: submit(data?: any) { // THE FOLLOWING CODE WORKS, BUT IT'S ...

Showcasing an input field once a specific button is pressed in an Angular application

When triggered, I am looking for a blank panel that will display a text box within the same panel. This functionality should be implemented using Angular. ...