<TopBlock>

Several type utilities exist within Prisma Client that can assist in the creation of highly type-safe extensions.

</TopBlock>

## Type Utilities

[Prisma Client type utilities](/orm/prisma-client/type-safety) are utilities available within your application and Prisma Client extensions and provide useful ways of constructing safe and extendable types for your extension.

The type utilities available are:

- `Exact<Input, Shape>`: Enforces strict type safety on `Input`. `Exact` makes sure that a generic type `Input` strictly complies with the type that you specify in `Shape`. It [narrows](https://www.typescriptlang.org/docs/handbook/2/narrowing.html) `Input` down to the most precise types.
- `Args<Type, Operation>`: Retrieves the input arguments for any given model and operation. This is particularly useful for extension authors who want to do the following:
  - Re-use existing types to extend or modify them.
  - Benefit from the same auto-completion experience as on existing operations.
- `Result<Type, Arguments, Operation>`: Takes the input arguments and provides the result for a given model and operation. You would usually use this in conjunction with `Args`. As with `Args`, `Result` helps you to re-use existing types to extend or modify them.
- `Payload<Type, Operation>`: Retrieves the entire structure of the result, as scalars and relations objects for a given model and operation. For example, you can use this to determine which keys are scalars or objects at a type level.

The following example creates a new operation, `exists`, based on `findFirst`. It has all of the arguments that `findFirst`.

```ts
const prisma = new PrismaClient().$extends({
  model: {
    $allModels: {
      // Define a new `exists` operation on all models
      // T is a generic type that corresponds to the current model
      async exists<T>(
        // `this` refers to the current type, e.g. `prisma.user` at runtime
        this: T,

        // The `exists` function will use the `where` arguments from the current model, `T`, and the `findFirst` operation
        where: Prisma.Args<T, 'findFirst'>['where']
      ): Promise<boolean> {
        // Retrieve the current model at runtime
        const context = Prisma.getExtensionContext(this)

        // Prisma Client query that retrieves data based
        const result = await (context as any).findFirst({ where })
        return result !== null
      },
    },
  },
})

async function main() {
  const user = await prisma.user.exists({ name: 'Alice' })
  const post = await prisma.post.exists({
    OR: [
      { title: { contains: 'Prisma' } },
      { content: { contains: 'Prisma' } },
    ],
  })
}
```

## Add a custom property to a method

The following example illustrates how you can add custom arguments, to a method in an extension:

```ts highlight=16
type CacheStrategy = {
  swr: number
  ttl: number
}

const prisma = new PrismaClient().$extends({
  model: {
    $allModels: {
      findMany<T, A>(
        this: T,
        args: Prisma.Exact<
          A,
          // For the `findMany` method, use the arguments from model `T` and the `findMany` method
          // and intersect it with `CacheStrategy` as part of `findMany` arguments
          Prisma.Args<T, 'findMany'> & CacheStrategy
        >
      ): Prisma.Result<T, A, 'findMany'> {
        // method implementation with the cache strategy
      },
    },
  },
})

async function main() {
  await prisma.post.findMany({
    cacheStrategy: {
      ttl: 360,
      swr: 60,
    },
  })
}
```

The example here is only conceptual. For the actual caching to work, you will have to implement the logic. If you're interested in a caching extension/ service, we recommend taking a look at [Prisma Accelerate](https://www.prisma.io/accelerate).

---

# Shared packages & examples