> ## Documentation Index
> Fetch the complete documentation index at: https://docs.cbrock.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Quick Start

> Get up and running with ts-chas in minutes.

<Steps>
  <Step title="Install">
    ```bash theme={null}
    npm install ts-chas
    ```

    See the [Installation page](/installation) for yarn/pnpm commands and TypeScript requirements.
  </Step>

  <Step title="Your first Result">
    `chas.fromPromise` wraps any Promise and maps thrown errors into a typed value. The result is a `ResultAsync<T, E>` that's awaitable, chainable, and explicit about what can go wrong.

    ```typescript theme={null}
    import { chas } from 'ts-chas';

    interface User {
      id: number;
      name: string;
    }

    function fetchUser(id: number): chas.ResultAsync<User, string> {
      return chas.fromPromise(
        fetch(`/api/users/${id}`).then(res => res.json()),
        (e) => `Fetch failed: ${e}`
      );
    }

    const result = await fetchUser(1)
      .map(user => user.name)          // transform the success value
      .mapErr(err => err.toUpperCase()); // transform the error

    if (result.isOk()) {
      console.log(`Hello, ${result.value}`);
    } else {
      console.error(result.error); // "FETCH FAILED: ..."
    }
    ```
  </Step>

  <Step title="Validate input with Guard">
    `is` from `ts-chas/guard` gives you chainable type predicates you can use inline or combine into full schemas.

    ```typescript theme={null}
    import { is, defineSchemas, type InferSchema } from 'ts-chas/guard';

    // Inline type predicate — works as a standard TypeScript guard
    const isValidEmail = is.string.trim().email.min(5);

    if (isValidEmail(someInput)) {
      // someInput is narrowed to `string` here
      console.log('Valid email:', someInput);
    }

    // Schema parsing — returns Result<T, GuardErr[]> with no try/catch
    const schemas = defineSchemas({
      UserPayload: {
        name: is.string.min(1),
        email: is.string.email,
        age: is.number.gte(18).error('Must be 18 or older'),
      },
    });

    type UserPayload = InferSchema<typeof schemas.UserPayload>;

    const parsed = schemas.UserPayload.parse(incomingJson);

    if (parsed.isOk()) {
      saveUser(parsed.value); // typed as UserPayload
    } else {
      console.error(parsed.error.map(e => e.message).join('\n'));
    }
    ```
  </Step>

  <Step title="A resilient Task">
    `Task` wraps an async operation lazily, which means it does not run until you call `.execute()`. You can attach retries, timeouts, and other resilience patterns before execution.

    ```typescript theme={null}
    import { Task } from 'ts-chas/task';

    const fetchData = Task.from(
      () => fetch('/api/data').then(res => res.json()),
      (e) => new Error(`Request failed: ${e}`)
    );

    const result = await fetchData
      .retry(3, { delay: 500, factor: 2 }) // up to 3 retries, exponential backoff
      .timeout(5000, () => new Error('Request timed out'))
      .execute();

    if (result.isOk()) {
      console.log(result.value);
    }
    ```
  </Step>

  <Step title="Putting it together">
    Here is a \~15-line end-to-end example that validates incoming request data with Guard, fetches a remote resource with Result, and wraps the whole thing in a resilient Task.

    ```typescript theme={null}
    import { chas } from 'ts-chas';
    import { is, defineSchemas } from 'ts-chas/guard';
    import { Task } from 'ts-chas/task';

    const schemas = defineSchemas({
      Request: { userId: is.string.uuid('v4') },
    });

    function handleRequest(body: unknown) {
      return Task.from(async () => {
        // Validate input — parse() returns a Result, unwrap throws on error
        const { userId } = schemas.Request.parse(body).unwrap();

        // Fetch with explicit error typing
        const user = await chas
          .fromPromise(
            fetch(`/api/users/${userId}`).then(r => r.json()),
            (e) => new Error(`Fetch failed: ${e}`)
          )
          .map(data => data as { id: string; name: string });

        return user;
      }, (e) => e instanceof Error ? e : new Error(String(e)))
        .retry(2)
        .timeout(8000, () => new Error('Request timed out'));
    }

    const result = await handleRequest(req.body).execute();

    if (result.isOk()) {
      console.log('User:', result.value.name);
    } else {
      console.error('Error:', result.error.message);
    }
    ```
  </Step>
</Steps>

<Note>
  These examples only scratch the surface. Head to [Core Concepts](/concepts/result) for a deeper dive into Result, Guard, Task, Tagged Errors, Option, and Pipe/Flow.
</Note>
