C3 AI Documentation Home

Type Meta Restrictions in C3 DSL

Some APIs accept a Type as a parameter. In these cases, you may need to limit the valid Types to those that mix a required interface. Use Type meta restrictions to ensure the Type you pass meets the structural requirements defined by the interface.

How type meta restrictions work

A type meta restriction uses double angle brackets (<< >>) to specify that a parameter must reference a Type that mixes a specific interface. The following example shows the basic syntax.

Type
entityType: Type<<Persistable>>

This field must be assigned a Type, such as User or Product, that mixes Persistable. The field holds a Type, not an instance of that Type.

Meta restriction syntax

The following pattern defines a meta restriction.

Type
fieldName: Type<<RestrictionType>>

RestrictionType must represent the capability you require. Use a Type that defines only the interface or behavior needed by the API.

Database administration example

The next example shows how to restrict database operations to persistable Types. This prevents accidental use of non-persistable Types at compile time.

Type
type DbAdmin {
  createTable: member function(entityType: !Type<<Persistable>>): boolean
  upsertIndex: member function(entityType: !Type<<Persistable>>, index: !string): boolean
}

The following usage examples show valid and invalid calls.

JavaScript
// Valid
DbAdmin.createTable(User);
DbAdmin.createTable(Product);

// Invalid
// DbAdmin.createTable(String);

Generic restrictions and meta restrictions

Generic restrictions apply to instances of a Type. Meta restrictions apply to the Type itself. The examples below show this difference.

Type
// Generic restriction
type Container<T: Persistable> {
  items: [T]
}
Type
// Meta restriction
type DatabaseManager {
  entityType: Type<<Persistable>>
}

Common usage patterns

The following sections show common scenarios where meta restrictions provide clear validation and safer API design.

Seed data

Use meta restrictions when you want to ensure that only seed data Types are valid. This applies when loading or managing application seed data.

Type
type PackageManager {
  seedDataDep: member function(seedDataType: !Type<<SeedData>>, dependencyName: !string): !SeedData
  createSeedData: member function(seedDataType: !Type<<SeedData>>, data: !map<string, any>): !SeedData
}

Event system

You can use meta restrictions to ensure that event-related APIs only accept Types that implement the event contract.

Type
type EventLogger {
  hasListeners: member function(eventType: !Type<<Event>>): boolean
  subscribe: member function(eventType: !Type<<Event>>, handler: !lambda(event: !Event))
}

Feature evaluation

Some APIs operate on feature-evaluatable Types. Meta restrictions help prevent invalid feature evaluation calls.

Type
type FeatureSet {
  forName: function(subjectType: !Type<<FeatureEvaluatable>>, featureName: !string): !FeatureBase
}

REST handlers

Use meta restrictions when a server configuration must only accept Types that implement specific handler interfaces.

Type
type HttpServerConfig {
  defaultHandler: Type<<Restful>>
  registerHandler: member function(path: !string, handlerType: !Type<<Restful>>): void
}

Advanced usage

Meta restrictions can be combined with generics and used in more complex APIs. The following examples show advanced usage patterns.

Combining with generics

Some APIs work with a specific subclass of Event and also need to validate the Type passed in. Meta restrictions and generic parameters can be used together.

Type
type EventProcessor<E: Event> {
  processEvent: member function(eventType: !Type<<E>>, eventData: !E): !ProcessingResult
}

Multiple restrictions

Some APIs require multiple restricted Type parameters. Use separate meta restrictions for each parameter.

Type
type DataValidator {
  validateEntity: member function(entityType: !Type<<Persistable>>, rule: !Type<<ValidationRule>>): !ValidationResult
}

How the C3 Agentic AI Platform enforces restrictions

Meta restrictions are validated during compilation. The C3 Agentic AI Platform also performs validation at runtime when evaluating arguments. You can inspect meta restrictions programmatically to understand their structure.

JavaScript
var field = MyType.meta().fieldType("entityType");
var restriction = field.valueType().metaRestriction();
var isValid = SomeType.meta().isA(restriction.dereference());

Best practices

Use restriction Types that describe a meaningful capability. Document the purpose of each meta restriction in the Type definition. Prefer meta restrictions when an API takes a Type as an argument and must enforce structural requirements.

See also

Was this page helpful?