or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

built-in-validators.mddata-transformation.mderror-handling.mdgeneric-types.mdindex.mdscope-modules.mdstring-processing.mdtype-creation.md
tile.json

scope-modules.mddocs/

Scope & Modules

Organization system for managing type definitions, creating reusable modules, and sharing types across projects.

Capabilities

Scope Creation

Create custom scopes to organize and share type definitions.

/**
 * Create a new scope with type definitions
 * @param def - Object containing type definitions and aliases
 * @param config - Optional configuration for the scope
 * @returns Scope instance with defined types
 */
function scope<const def>(
  def: scope.validate<def>,
  config?: ArkScopeConfig
): Scope<scope.infer<def>>;

interface Scope<$ = {}> {
  /** Type parser bound to this scope */
  type: TypeParser<$>;
  
  /** Export types as a reusable module */
  export(): Module<{ [k in exportedNameOf<$>]: $[k] }>;
  
  /** Resolve a specific type by name */
  resolve<name extends exportedNameOf<$>>(
    name: name
  ): instantiateExport<$[name], $>;
  
  /** Access to all defined aliases */
  aliases: Record<string, unknown>;
  
  /** Internal scope representation */
  internal: InternalScope<$>;
}

Usage Examples:

import { scope } from "arktype";

// Create a custom scope
const myScope = scope({
  user: {
    id: "string.uuid",
    name: "string.trim",
    email: "string.email",
    age: "number.integer >= 0"
  },
  
  admin: {
    permissions: "string[]",
    level: "1 | 2 | 3"
  },
  
  // Reference other types in the scope
  userWithAdmin: {
    user: "user",
    admin: "admin"
  }
});

// Use types from the scope
const User = myScope.type("user");
const Admin = myScope.type("admin");

// Resolve types directly
const UserType = myScope.resolve("user");

Module System

Export and import type collections for reuse across projects.

/**
 * Create a module from scope definitions
 * @param def - Type definitions to export
 * @param config - Optional module configuration
 * @returns Module with exported types
 */
function module<const def>(
  def: scope.validate<def>,
  config?: ArkScopeConfig
): Module<{ [k in exportedNameOf<scope.infer<def>>]: scope.infer<def>[k] }>;

interface Module<$ extends {} = {}> {
  /** Access exported types and utilities */
  [K in keyof $]: instantiateExport<$[K], $>;
}

Usage Examples:

// Create a reusable module
const userModule = scope({
  user: {
    id: "string.uuid",
    name: "string",
    email: "string.email"
  },
  
  createUser: {
    name: "string",
    email: "string.email"
  },
  
  updateUser: {
    id: "string.uuid",
    name: "string?",
    email: "string.email?"
  }
}).export();

// Use in another scope
const apiScope = scope({
  // Import from module
  ...userModule,
  
  response: {
    data: "user",
    status: "'success' | 'error'"
  }
});

Generic Definitions in Scopes

Define parameterized types within scopes.

// Generic definition syntax in scopes
type GenericDeclaration<
  name extends string = string,
  params extends ParameterString = ParameterString  
> = `${name}${params}`;

// Usage in scope definitions
const scopeWithGenerics = scope({
  "container<t>": {
    value: "t",
    count: "number"
  },
  
  "pair<k, v>": {
    key: "k", 
    value: "v"
  }
});

Usage Examples:

// Define generic types in scope
const genericScope = scope({
  "box<t>": {
    value: "t",
    isEmpty: "boolean"
  },
  
  "result<t, e>": {
    data: "t",
    error: "e",
    isOk: "boolean"
  },
  
  // Use generics within scope
  stringBox: "box<string>",
  numberResult: "result<number, string>"
});

// Use the generic types
const StringBox = genericScope.type("box<string>");
const ApiResult = genericScope.type("result<object, string>");

Scope Configuration

Customize scope behavior and type resolution.

interface ArkScopeConfig extends ArkSchemaConfig {
  /** Name for the scope (used in error messages) */
  name?: string;
  
  /** Custom keyword configurations */
  keywords?: KeywordConfig;
  
  /** Whether to use prereduced aliases for performance */
  prereducedAliases?: boolean;
}

interface KeywordConfig {
  [keywordName: string]: TypeMeta.Collapsible;
}

Usage Examples:

// Named scope with custom config
const apiScope = scope({
  userId: "string.uuid",
  timestamp: "string.date.iso"
}, {
  name: "API",
  prereducedAliases: true
});

// Scope with custom keyword behavior
const strictScope = scope({
  strictString: "string",
  strictNumber: "number"
}, {
  name: "StrictValidation",
  keywords: {
    "string": { description: "Must be a non-empty string" }
  }
});

Type Parser in Scopes

Each scope provides its own type parser with access to scope definitions.

interface TypeParser<$ = {}> {
  /** Create types using this scope's definitions */
  <const def>(def: type.validate<def, $>): Type<type.infer<def, $>>;
  
  /** Create generic types */
  <const params extends ParameterString, const def>(
    params: validateParameterString<params, $>,
    def: type.validate<def, $, baseGenericConstraints<parseValidGenericParams<params, $>>>
  ): Generic<parseValidGenericParams<params, $>, def, $>;
  
  /** Access to scope and ambient types */
  $: Scope<$>;
  keywords: typeof keywords;
  
  // All standard type creation methods are available
  unit: UnitTypeParser<$>;
  enumerated: EnumeratedTypeParser<$>;
  instanceOf: InstanceOfTypeParser<$>;
  valueOf: ValueOfTypeParser<$>;
  or: NaryUnionParser<$>;
  and: NaryIntersectionParser<$>;
  merge: NaryMergeParser<$>;
  pipe: NaryPipeParser<$>;
}

Usage Examples:

const myScope = scope({
  userId: "string.uuid",
  userAge: "number.integer >= 0"
});

// Use scope's type parser
const { type } = myScope;

// Create types using scope definitions
const UserProfile = type({
  id: "userId",        // References scope definition
  age: "userAge",      // References scope definition
  name: "string"       // Standard type
});

// Generic with scope types
const UserContainer = type("<t>", {
  user: {
    id: "userId",
    data: "t"
  }
});

Module Import/Export Patterns

Advanced patterns for sharing types between modules.

interface Scope<$ = {}> {
  /** Import module with private aliases (prefixed with #) */
  import(): Module<{ [k in exportedNameOf<$> as PrivateDeclaration<k>]: $[k] }>;
  
  /** Import specific types with private aliases */
  import<names extends exportedNameOf<$>[]>(
    ...names: names
  ): BoundModule<
    { [k in names[number] as PrivateDeclaration<k>]: $[k] },
    $
  >;
  
  /** Export all types publicly */
  export(): Module<{ [k in exportedNameOf<$>]: $[k] }>;
  
  /** Export specific types only */
  export<names extends exportedNameOf<$>[]>(
    ...names: names
  ): BoundModule<{ [k in names[number]]: $[k] }, $>;
}

Usage Examples:

// Create a base scope
const baseScope = scope({
  id: "string.uuid",
  timestamp: "string.date.iso",
  internalHelper: "string" // Won't be exported
});

// Export only specific types
const publicModule = baseScope.export("id", "timestamp");

// Use in another scope
const userScope = scope({
  // Import with private prefix
  ...baseScope.import("id", "timestamp"),
  
  user: {
    id: "#id",           // References imported private type
    createdAt: "#timestamp",
    name: "string"
  }
});

// Create full module
const userModule = userScope.export();

Submodule Organization

Organize related types into submodules for better structure.

interface Submodule<exports extends {}> {
  /** Access to all exports in the submodule */
  [K in keyof exports]: exports[K];
  
  /** Root type if defined */
  root?: exports extends { root: infer R } ? R : never;
}

// Usage pattern for nested modules
const complexModule = scope({
  user: {
    id: "string.uuid",
    profile: {
      name: "string",
      email: "string.email"
    }
  },
  
  // Submodule pattern
  validation: scope({
    email: "string.email",
    phone: "string", // Pattern for phone
    required: "string >= 1"
  }).export()
}).export();

Usage Examples:

// Access submodule types
const emailValidator = complexModule.validation.email;
const userType = complexModule.user;

// Nested scope organization
const appScope = scope({
  auth: scope({
    token: "string.uuid",
    credentials: {
      username: "string",
      password: "string >= 8"
    }
  }).export(),
  
  api: scope({
    request: {
      method: "'GET' | 'POST' | 'PUT' | 'DELETE'",
      url: "string.url",
      headers: "Record<string, string>?"
    },
    response: {
      status: "number.integer >= 100 <= 599",
      data: "unknown"
    }
  }).export()
});

// Use nested types
const LoginRequest = appScope.type({
  credentials: "auth.credentials",
  endpoint: "api.request"
});