← Files TemporalARCHIVED FILE

skills/temporal-developer/references/typescript/typescript.md

7.57 KB · Oct 2, 2026 · 00:08 UTC

↓ Download file

# Temporal TypeScript SDK Reference

## Overview

The Temporal TypeScript SDK provides a modern Promise based approach to building durable workflows. Workflows are bundled and run in an isolated runtime with automatic replacements for determinism protection.

**CRITICAL**: All `@temporalio/*` packages must have the same version number.

## Understanding Replay

Temporal workflows are durable through history replay. For details on how this works, see `references/core/determinism.md`.

## Quick Start

**Add Dependencies:** Install the Temporal SDK packages (use the package manager appropriate for your project):

```bash
npm install @temporalio/client @temporalio/worker @temporalio/workflow @temporalio/activity @temporalio/envconfig
```

Note: if you are working in production, it is strongly advised to use ~ version constraints, i.e. `npm install ... --save-prefix='~'` if using NPM.

**activities.ts** - Activity definitions (separate file to distinguish workflow vs activity code):

```typescript
export async function greet(name: string): Promise<string> {
  return `Hello, ${name}!`;
}
```

**workflows.ts** - Workflow definition (use type-only imports for activities):

```typescript
import { proxyActivities } from '@temporalio/workflow';
import type * as activities from './activities';

const { greet } = proxyActivities<typeof activities>({
  startToCloseTimeout: '1 minute',
});

export async function greetingWorkflow(name: string): Promise<string> {
  return await greet(name);
}
```

**worker.ts** - Worker setup (registers activity and workflow, runs indefinitely and processes tasks):

```typescript
import { NativeConnection, Worker } from '@temporalio/worker';
import { loadClientConnectConfig } from '@temporalio/envconfig';
import * as activities from './activities';

async function run() {
  const config = loadClientConnectConfig();
  const connection = await NativeConnection.connect(config.connectionOptions);
  const worker = await Worker.create({
    connection,
    namespace: config.namespace,
    workflowsPath: require.resolve('./workflows'), // For production, use workflowBundle instead
    activities,
    taskQueue: 'greeting-queue',
  });
  await worker.run();
}

run().catch(console.error);
```

**Start the dev server:** Start `temporal server start-dev` in the background.

**Start the worker:** Run `npx ts-node worker.ts` in the background.

**client.ts** - Start a workflow execution:

```typescript
import { Client, Connection } from '@temporalio/client';
import { loadClientConnectConfig } from '@temporalio/envconfig';
import { greetingWorkflow } from './workflows';
import { v4 as uuid } from 'uuid';

async function run() {
  const config = loadClientConnectConfig();
  const connection = await Connection.connect(config.connectionOptions);
  const client = new Client({ connection, namespace: config.namespace });

  const result = await client.workflow.execute(greetingWorkflow, {
    workflowId: uuid(),
    taskQueue: 'greeting-queue',
    args: ['my name'],
  });

  console.log(`Result: ${result}`);
}

run().catch(console.error);
```

**Run the workflow:** Run `npx ts-node client.ts`. Should output: `Result: Hello, my name!`.

## Key Concepts

### Workflow Definition

- Async functions exported from workflow file
- Use `proxyActivities()` with type-only imports
- Use `defineSignal()`, `defineQuery()`, `defineUpdate()`, `setHandler()` for handlers

### Activity Definition

- Regular async functions
- Can perform I/O, network calls, etc.
- Use `heartbeat()` for long operations

### Worker Setup

- Load connection settings with `loadClientConnectConfig()` and pass them to `NativeConnection.connect()`
- Pass `namespace: config.namespace` to `Worker.create()` - `NativeConnection` carries no namespace, and the Worker defaults to `default` without it
- Use `Worker.create()` with `workflowsPath` (dev) or `workflowBundle` (production) - see `references/typescript/gotchas.md`
- Import activities directly (not via proxy)

## File Organization Best Practice

**Keep Workflow definitions in separate files from Activity definitions.** The TypeScript SDK bundles workflow files separately. Minimizing workflow file contents improves Worker startup time.

```
my_temporal_app/
├── workflows/
│   └── greeting.ts      # Only Workflow functions
├── activities/
│   └── translate.ts     # Only Activity functions
├── worker.ts            # Worker setup, imports both
└── client.ts            # Client code to start workflows
```

**In the Workflow file, use type-only imports for activities:**

```typescript
// workflows/greeting.ts
import { proxyActivities } from '@temporalio/workflow';
import type * as activities from '../activities/translate';

const { translate } = proxyActivities<typeof activities>({
  startToCloseTimeout: '1 minute',
});
```

## Determinism Rules

The TypeScript SDK runs workflows in an isolated V8 sandbox.

**Automatic replacements:**

- `Math.random()` → deterministic seeded PRNG
- `Date.now()` → workflow start time
- `setTimeout` → deterministic timer

**Safe to use:**

- `sleep()` from `@temporalio/workflow`
- `condition()` for waiting
- Standard JavaScript operations

See `references/typescript/determinism.md` for detailed rules.

## Common Pitfalls

1. **Importing activities without `type`** - Use `import type * as activities`
2. **Version mismatch** - All @temporalio packages must match
3. **Direct I/O in workflows** - Use activities for external calls
4. **Missing `proxyActivities`** - Required to call activities from workflows
5. **Forgetting to bundle workflows** - Worker needs `workflowsPath` or `workflowBundle`
6. **Using workflowsPath in production** - Use `workflowBundle` for production (see `references/typescript/gotchas.md`)
7. **Forgetting to heartbeat** - Long-running activities need `heartbeat()` calls
8. **Logging in workflows** - For observability, use `import { log } from '@temporalio/workflow'` (routes through sinks). For temporary print debugging, `console.log()` is fine—it's direct and immediate, whereas `log` may lose messages on workflow errors.
9. **Forgetting to wait on activity calls** - Activity calls return Promises; you must eventually await them (directly or via `Promise.all()` for parallel execution)

## Writing Tests

See `references/typescript/testing.md` for info on writing tests.

## Additional Resources

### Reference Files

- **`references/typescript/patterns.md`** - Signals, queries, child workflows, saga pattern, etc.
- **`references/typescript/determinism.md`** - Essentials of determinism in TypeScript
- **`references/typescript/gotchas.md`** - TypeScript-specific mistakes and anti-patterns
- **`references/typescript/error-handling.md`** - ApplicationFailure, retry policies, non-retryable errors
- **`references/typescript/observability.md`** - Logging, metrics, tracing
- **`references/typescript/testing.md`** - TestWorkflowEnvironment, time-skipping, activity mocking
- **`references/typescript/advanced-features.md`** - Schedules, worker tuning, and more
- **`references/typescript/data-handling.md`** - Data converters, payload encryption, etc.
- **`references/typescript/external-storage.md`** - Claim-check pattern for large Payloads (S3 and GCS drivers, custom drivers, codec-server handling, multi-region durability)
- **`references/typescript/versioning.md`** - Patching API, workflow type versioning, Worker Versioning
- **`references/typescript/standalone-activities.md`** - Standalone Activities: run an Activity directly from a Client without a Workflow (Public Preview). Concept overview at `references/core/standalone-activities.md`.
- **`references/typescript/determinism-protection.md`** - V8 sandbox and bundling

SHA-256: 4dec38d4eaac17cc1ab30da2ffc459b8d83fbbe23086aca779d39242b5fdeb1f