Changelog #67

·

Improved typesafe task triggering

Eric Allam

Eric Allam

CTO, Trigger.dev

Image for Improved typesafe task triggering

Currently the only way to trigger a task in a typesafe way is to use the Task.trigger instance method:

Next.js

import { emailSequence } from "~/trigger/emails";
// 👆 import the emailSequence task
//app/email/route.ts
export async function POST(request: Request) {
//get the JSON from the request
const data = await request.json();
//trigger your task
const handle = await emailSequence.trigger({
to: data.email,
name: data.name,
});
//return a success response with the handle
return Response.json(handle);
}

This is great for most cases, but importing the task means importing anything the task depends on. This can lead to bloated applications, or worse, build failures because of some esoteric dependency that doesn't work when included in a Next.js 14.2.4 project (for example).

As of v3.0.0-beta.41, you can now trigger tasks using the tasks.trigger SDK function, passing in the type of the task only as a generic parameter:

Next.js

import { tasks } from "@trigger.dev/sdk/v3";
import type { emailSequence } from "~/trigger/emails";
// 👆 **type-only** import
//app/email/route.ts
export async function POST(request: Request) {
//get the JSON from the request
const data = await request.json();
// Pass the task type to `trigger()` as a generic argument, giving you full type checking
const handle = await tasks.trigger<typeof emailSequence>("email-sequence", {
// 👆 this ID is fully type safe as well
to: data.email,
name: data.name,
});
//return a success response with the handle
return Response.json(handle);
}

By importing only the type of the task, any dependencies the task has are not included in the build, and you get full type checking on the task payload, ID, and output.

This works with batchTrigger as well:

Next.js

import { tasks } from "@trigger.dev/sdk/v3";
import type { emailSequence } from "~/trigger/emails";
// 👆 **type-only** import
//app/email/route.ts
export async function POST(request: Request) {
//get the JSON from the request
const data = await request.json();
// Pass the task type to `batchTrigger()` as a generic argument, giving you full type checking
const batchHandle = await tasks.batchTrigger<typeof emailSequence>(
"email-sequence",
data.users.map((u) => ({ payload: { to: u.email, name: u.name } }))
);
//return a success response with the handle
return Response.json(batchHandle);
}

In addition, the handle returned from trigger and batchTrigger now carries extra type information about the output of the task, which can be used to retrieve the run output in a typesafe way:


import { tasks, runs } from "@trigger.dev/sdk/v3";
import type { emailSequence } from "~/trigger/emails";
// 👆 **type-only** import
async function main(email: string, name: string) {
// Pass the task type to `trigger()` as a generic argument, giving you full type checking
const handle = await tasks.trigger<typeof emailSequence>("email-sequence", {
to: email,
name,
});
const run = await runs.retrieve(handle);
return run.output; // 👈 run.output is now typed
}

There's more! We included a polling helper function to the runs SDK module, which can be used to poll for the completion of a task run:


import { tasks, runs } from "@trigger.dev/sdk/v3";
import type { emailSequence } from "~/trigger/emails";
// 👆 **type-only** import
async function main(email: string, name: string) {
// Pass the task type to `trigger()` as a generic argument, giving you full type checking
const handle = await tasks.trigger<typeof emailSequence>("email-sequence", {
to: email,
name,
});
// Poll for the completion of the task run
const run = await runs.poll(handle, { pollIntervalMs: 1000 });
return run.output; // 👈 run.output is now typed and complete
}

We've also added a triggerAndPoll helper function to the tasks SDK module, which can be used to trigger a task and poll for the completion of the task run in one go:


import { tasks } from "@trigger.dev/sdk/v3";
import type { emailSequence } from "~/trigger/emails";
async function main(email: string, name: string) {
// Pass the task type to `triggerAndPoll()` as a generic argument, giving you full type checking
const run = await tasks.triggerAndPoll<typeof emailSequence>(
"email-sequence",
{
to: email,
name,
},
{
pollIntervalMs: 1000,
}
);
return run.output; // 👈 run.output is now typed and complete
}

NOTE

These new SDK functions are meant to be used from your server-side code only. They also aren't meant to replace Task.triggerAndWait or Task.batchTriggerAndWait when running inside another task.

You'll find these updates in the @trigger.dev/[email protected] package. Give it a try and let us know what you think, or if we've missed anything!

Ready to start building?

Build and deploy your first task in 3 minutes.

Get started now