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

# is

> Type guard to check if value is CallData

Type guard that checks whether a value is a CallData instance. Provides TypeScript type narrowing.

## Signature

<Tabs>
  <Tab title="Namespace">
    ```typescript theme={null}
    function is(value: unknown): value is CallDataType
    ```
  </Tab>

  <Tab title="Class">
    ```typescript theme={null}
    CallData.is(value: unknown): value is CallDataType
    ```
  </Tab>
</Tabs>

## Parameters

* **value** - Value to check (any type)

## Returns

`boolean` - `true` if value is CallData instance (with type narrowing)

## Examples

<Tabs>
  <Tab title="Basic Usage">
    ```typescript theme={null}
    import { CallData, type CallDataType } from '@tevm/voltaire';

    const value: unknown = someFunction();

    if (CallData.is(value)) {
      // value is CallDataType here (type narrowed)
      const selector = CallData.getSelector(value);
      console.log(selector);
    }
    ```
  </Tab>

  <Tab title="Type Narrowing">
    ```typescript theme={null}
    import { CallData, type CallDataType } from '@tevm/voltaire';

    function process(input: string | CallDataType) {
      if (CallData.is(input)) {
        // input is CallDataType
        console.log("Size:", input.length);
        const selector = CallData.getSelector(input);
      } else {
        // input is string
        const calldata = CallData(input);
      }
    }
    ```
  </Tab>

  <Tab title="Array Filtering">
    ```typescript theme={null}
    import { CallData, type CallDataType } from '@tevm/voltaire';

    const mixed: unknown[] = [
      CallData("0xa9059cbb"),
      "not calldata",
      CallData.fromBytes(new Uint8Array([0x12, 0x34, 0x56, 0x78])),
      123,
    ];

    const calldata: CallDataType[] = mixed.filter(CallData.is);
    console.log("Found", calldata.length, "calldata instances");
    ```
  </Tab>
</Tabs>

## Type Narrowing

TypeScript narrows the type when `is()` returns true:

```typescript theme={null}
import { CallData, type CallDataType } from '@tevm/voltaire';

function handle(value: unknown) {
  // Before: value is unknown
  console.log(value.length); // ❌ Type error

  if (CallData.is(value)) {
    // After: value is CallDataType
    console.log(value.length); // ✅ OK
    console.log(CallData.toHex(value)); // ✅ OK
  }
}
```

## Comparison with isValid

<Tabs>
  <Tab title="is() - Type Guard">
    ```typescript theme={null}
    import { CallData, type CallDataType } from '@tevm/voltaire';

    function process(value: unknown) {
      if (CallData.is(value)) {
        // value is CallDataType (type narrowed)
        return CallData.toHex(value); // Direct use
      }
    }
    ```

    **Checks:** Already constructed CallData instance
    **Returns:** Type guard (`value is CallDataType`)
    **Use for:** Type narrowing, checking existing instances
  </Tab>

  <Tab title="isValid() - Validation">
    ```typescript theme={null}
    import { CallData } from '@tevm/voltaire';

    function process(value: unknown) {
      if (CallData.isValid(value)) {
        // value is still unknown (no narrowing)
        const calldata = CallData(value); // Must construct
        return CallData.toHex(calldata);
      }
    }
    ```

    **Checks:** Can be converted to CallData
    **Returns:** Simple boolean
    **Use for:** Input validation, pre-construction checks
  </Tab>
</Tabs>

## Use Cases

### Function Overloads

```typescript theme={null}
import { CallData, type CallDataType } from '@tevm/voltaire';

function processData(data: string): CallDataType;
function processData(data: CallDataType): CallDataType;
function processData(data: string | CallDataType): CallDataType {
  if (CallData.is(data)) {
    return data; // Already CallData
  } else {
    return CallData(data); // Convert from string
  }
}
```

### Union Type Handling

```typescript theme={null}
import { CallData, type CallDataType, type Bytecode } from '@tevm/voltaire';

function analyze(data: CallDataType | Bytecode) {
  if (CallData.is(data)) {
    // Handle as calldata
    const selector = CallData.getSelector(data);
    console.log("Function call:", selector);
  } else {
    // Handle as bytecode
    console.log("Contract code:", Bytecode.toHex(data));
  }
}
```

### Generic Functions

```typescript theme={null}
import { CallData, type CallDataType } from '@tevm/voltaire';

function logIfCallData<T>(value: T): T {
  if (CallData.is(value)) {
    console.log("CallData:", CallData.toHex(value));
  }
  return value;
}

// Usage
const result = logIfCallData(someValue); // Type preserved
```

### Type-Safe Caching

```typescript theme={null}
import { CallData, type CallDataType } from '@tevm/voltaire';

class Cache<T> {
  private data = new Map<string, T>();

  set(key: unknown, value: T): void {
    if (CallData.is(key)) {
      this.data.set(CallData.toHex(key), value);
    } else {
      throw new Error("Key must be CallData");
    }
  }

  get(key: unknown): T | undefined {
    if (CallData.is(key)) {
      return this.data.get(CallData.toHex(key));
    }
    return undefined;
  }
}
```

## Implementation

Checks for CallData brand:

```typescript theme={null}
// Simplified implementation
import { brand } from './brand.js';

export function is(value: unknown): value is CallDataType {
  return (
    value instanceof Uint8Array &&
    (value as any)[brand] === "CallData" &&
    value.length >= 4
  );
}
```

Checks:

1. Is Uint8Array
2. Has CallData brand
3. Minimum 4 bytes (selector)

## Performance

Very fast (just property checks):

```typescript theme={null}
// Benchmark: 10M iterations
const calldata = CallData("0xa9059cbb");
const notCalldata = "0xa9059cbb";

console.time("is (calldata)");
for (let i = 0; i < 10_000_000; i++) {
  CallData.is(calldata);
}
console.timeEnd("is (calldata)");
// ~80ms

console.time("is (not calldata)");
for (let i = 0; i < 10_000_000; i++) {
  CallData.is(notCalldata);
}
console.timeEnd("is (not calldata)");
// ~30ms (fails fast)
```

## Type Safety Example

```typescript theme={null}
import { CallData, type CallDataType } from '@tevm/voltaire';

// Function that requires CallData
function process(data: CallDataType) {
  return CallData.decode(data, abi);
}

// Safe wrapper with type guard
function safeProcess(data: unknown) {
  if (!CallData.is(data)) {
    throw new Error("Expected CallData");
  }

  return process(data); // Type-safe
}
```

## Branded Type Pattern

CallData uses Symbol branding for type safety:

```typescript theme={null}
import { brand } from './brand.js';

// Type definition
export type CallDataType = Uint8Array & {
  readonly [brand]: "CallData";
};

// Runtime check
export function is(value: unknown): value is CallDataType {
  return (
    value instanceof Uint8Array &&
    (value as any)[brand] === "CallData"
  );
}
```

This prevents accidental mixing of Uint8Arrays with CallData.

## Related

* [isValid](/primitives/calldata/is-valid) - Validate input can be converted
* [from](/primitives/calldata/from) - Universal constructor
* [Branded Types](/getting-started/branded-types) - Understanding branding
* [equals](/primitives/calldata/equals) - Compare CallData instances
