next-cool-action
Types

Infer types

Learn how to infer types with next-cool-action.

Infer types

next-cool-action, since version 7.6.4, exports utility types for type inference. Here's a guide on how to use them.

Suppose we have declared this cool action client:

src/lib/cool-action.ts
import { z } from "zod";
import { createCoolActionClient, createMiddleware } from "next-cool-action";
import { getSessionData } from "@/services/auth"

// Here we declare a standalone auth middleware.
export const authMiddleware = createMiddleware<{
  ctx: { sessionToken: string };
  metadata: { actionName: string };
}>().define(async ({ ctx, next }) => {
  const { sessionId, userId } = await getSessionData(ctx.sessionToken);

  return next({
    ctx: {
      sessionId,
      userId,
    },
  });
});

// Here we declare the cool action client.
export const actionClient = createCoolActionClient({
  defineMetadataSchema: () => {
    return z.object({
      actionName: z.string(),
    });
  },
  handleServerError: (e) => {
    console.error("Action error:", e.message);
    return {
      errorMessage: e.message,
    };
  },
})
  .use(async ({ next }) => {
    return next({
      ctx: {
        sessionToken: "someToken",
      },
    });
  })
  .use(authMiddleware);

And then this action function:

src/app/test-action.ts
"use server";

import { z } from "zod";
import { actionClient } from "@/lib/cool-action";

const testActionSchema = z.object({
  username: z.string(),
});

const testActionBindArgsSchemas: [email: z.ZodString, age: z.ZodNumber] = [z.string(), z.number()];

export const testAction = actionClient
  .use(authMiddleware)
  .inputSchema(testActionSchema)
  .bindArgsSchemas(testActionBindArgsSchemas)
  .action(async () => {
    return {
      successful: true,
    };
  });

We'll use these exported functions in the following examples.

/

The library exports several utility types from the root path that help you infer types of a cool action client, a middleware function or a cool action function.

Here's the list of utility types exported from next-cool-action path:

  • InferCoolActionFnInput: infer input types of a cool action function
  • InferCoolActionFnResult: infer result type of a cool action function
  • InferMiddlewareFnNextCtx: infer the type of context returned by a middleware function using the next function
  • InferCtx: infer the type of context of a cool action client, or the context passed to a middleware function
  • InferMetadata: infer the type of metadata of a cool action client or middleware function
  • InferServerError: infer the type of the serverError of a cool action function, middleware function or cool action function

Example

import type {
  InferCtx,
  InferMetadata,
  InferMiddlewareFnNextCtx,
  InferCoolActionFnInput,
  InferCoolActionFnResult,
  InferServerError,
} from "next-cool-action";
import type { actionClient, authMiddleware } from "@/lib/cool-action";
import type { testAction } from "@/app/test-action";

// Use `InferCoolActionFnInput` to infer the input types of a cool action function.
type inferredTestActionInput = InferCoolActionFnInput<typeof testAction>;
/*
{
  clientInput: {
    username: string;
  };
  bindArgsClientInputs: [email: string, age: number];
  parsedInput: {
    username: string;
  };
  bindArgsParsedInputs: [email: string, age: number];
}
*/

// Use `InferCoolActionFnResult` to infer the result type of a cool action function.
type inferredTestActionResult = InferCoolActionFnResult<typeof testAction>;
/*
{
  data?: {
    successful: boolean;
  } | undefined;
  serverError?: string | undefined;
  validationErrors?: {
    _errors?: string[];
    username?: {
      _errors?: string[];
    } | undefined;
  } | undefined;
  bindArgsValidationErrors?: [email: { _errors?: string[] }, age: { _errors?: string[] }] | undefined;
}
*/

// Use `InferMiddlewareFnNextCtx` to infer the type of the context returned by a middleware function using
// the `next` function.
type inferredAuthMiddlewareNextCtx = InferMiddlewareFnNextCtx<typeof authMiddleware>;
/*
{
  sessionId: string;
  userId: string;
}
*/

// Use `InferCtx` to infer the type of the context of a cool action client, or the context passed to a
// middleware function. Here's an example with a cool action client:
type inferredCoolActionClientCtx = InferCtx<typeof actionClient>;
/*
{
  sessionToken: string;
} & {
  sessionId: string;
  userId: string;
}
*/

// Use `InferMetadata` to infer the type of the metadata of a cool action client or middleware function.
// Here's an example with a middleware function:
type inferredMiddlewareMetadata = InferMetadata<typeof authMiddleware>;
/*
{
  actionName: string;
}
*/

// Use `InferServerError` to infer the type of the `serverError` of a cool action client, middleware function,
// or cool action function. Here's an example with a cool action:
type inferredServerError = InferServerError<typeof testAction>;
/*
{
  errorMessage: string;
}
*/

/hooks

The library also exports three types from the /hooks path that help you infer types when using useAction, useOptimisticAction and useStateAction hooks.

Here's a list of utility types exported from next-cool-action/hooks:

  • InferUseActionHookReturn: infers the return type of the useAction hook - only works with actions defined using the action method
  • InferUseOptimisticActionHookReturn: infers the return type of the useOptimisticAction hook - only works with stateless actions defined using the action method
  • InferUseStateActionHookReturn - DEPRECATED: infers the return type of the useStateAction hook - only works with stateful actions defined using the stateAction method

Example

import type { testAction } from "@/app/test-action";

// Use `InferUseActionHookReturn` to infer the return type of the `useAction` hook with a provided
// cool action function.
type inferredTestActionHookReturn = InferUseActionHookReturn<typeof testAction>;
/*
{
  execute: (input: { username: string }) => void;
  executeAsync: (input: { username: string }) => Promise<CoolActionResult>;
  input: { username: string };
  result: CoolActionResult;
  reset: () => void;
  status: HookActionStatus;
} & HookShorthandStatus
*/

// Use `InferUseActionHookReturn` to infer the return type of the `useOptimisticAction` hook with a provided
// cool action function. You can pass the server state as the second generic parameter, which defaults
// to `any`.
type inferredTestActionOptimisticHookReturn = InferUseOptimisticActionHookReturn<
  typeof testAction,
  { myServerState: { foo: string } }
>;
/*
{
  execute: (input: { username: string }) => void;
  executeAsync: (input: { username: string }) => Promise<CoolActionResult>;
  input: { username: string };
  result: CoolActionResult;
  reset: () => void;
  status: HookActionStatus;
  optimisticState: { myServerState: { foo: string } };
} & HookShorthandStatus
*/

// Use `InferUseStateActionHookReturn` to infer the return type of the `useStateAction` hook with a
// provided stateful cool action. In this case, by providing the type of `testAction` as the
// generic parameter will, the resulting type will be `never`, because `testAction` is not defined
// using `stateAction()` method. Supposing that we change the definition of the function to be stateful,
// the resulting type will be:
type inferredTestActionStateHookReturn = InferUseStateActionHookReturn<typeof testAction>;
/*
{
  execute: (input: { username: string }) => void;
  input: { username: string };
  result: CoolActionResult;
  status: HookActionStatus;
} & HookShorthandStatus
*/

On this page