# Helpers (/docs/products/dash-dots/reference/dash-api/helpers)

Import these from `@monimesl/dot-runtime`. A call that fails rejects with a `DashError`, and its `code` says why.

```ts
import { errorMessage, isDashError, unlessCancelled } from '@monimesl/dot-runtime';

const photo = await unlessCancelled(this.dash.media.pickPhoto({ source: 'camera' }));
if (!photo) return; // The person closed the camera.
```

## `isDashError`

```ts
isDashError<Code extends DashErrorCode>(error: unknown, ...codes: Code[]): error is DashError
```

Whether `error` is a Dash call's error, with one of `codes` when you give any. Inside the check, TypeScript knows its `code`.

## `errorMessage`

```ts
errorMessage(error: unknown): string
```

The message to show for anything a call threw, even if it isn't an Error.

## `unlessCancelled`

```ts
unlessCancelled<Result>(call: PromiseLike<Result>): Promise<Result | undefined>
```

Waits for a call, such as a picker, and gives undefined if the person closed it or it was cancelled. Other errors still throw.

## `latest`

```ts
latest(): <Result>(call: DashRequest<Result>) => DashRequest<Result>
```

Each call given to it cancels the one before, so an older answer can't arrive after a newer one. The cancelled call rejects with `cancelled`, which `unlessCancelled` turns into undefined.

```ts
const search = latest();

// In an action: an older search that answers late gives undefined.
const answer = await unlessCancelled(search(this.dash.network.http.request({ url, as: 'json' })));
```

## `debounce`

```ts
debounce(milliseconds: number): (dash: Dash) => Promise<boolean>
```

Resolves true once `milliseconds` pass without another call, such as a pause in typing, and false when a newer call cut the wait short. Pass it the page's `this.dash`.

```ts
const typingPause = debounce(400);

// In an action that runs on each keystroke: go on only once the person stops typing.
if (!(await typingPause(this.dash))) return;
```
