Collections and records
Typra preserves the collection shape from TypeSpec and lets each target choose the idiomatic runtime type.
model FixtureRoot { tags: string[]; metadata?: Record<unknown>; contentItems: FixtureContent[];}| TypeSpec | Typra mapping |
|---|---|
string[] | Array or list of scalar values. |
FixtureContent[] | Array or list of nested model values, including polymorphic dispatch when the item type is discriminated. |
Record<unknown> | Dictionary-shaped metadata with unknown values. |
Generated tests exercise scalar arrays, nested object arrays, dictionaries, and polymorphic collections from fixture samples.
Generated shape
Section titled “Generated shape”export class FixtureRoot { tags: string[] = []; metadata?: Record<string, unknown> | undefined; contentItems: FixtureContent[] = [];
static loadContentItems(data: Record<string, unknown>[] | unknown[], context?: LoadContext): FixtureContent[] { return data.map(item => FixtureContent.load(item as Record<string, unknown>, context)); }
static saveContentItems(items: FixtureContent[], context?: SaveContext): Record<string, unknown>[] { return items.map(item => item.save(context)); }}@dataclassclass FixtureRoot: tags: list[str] = field(default_factory=list) metadata: dict[str, Any] | None = None content_items: list[FixtureContent] = field(default_factory=list)
@staticmethod def load_content_items(data: dict | list, context: LoadContext | None) -> list[FixtureContent]: if isinstance(data, dict): data = [{"name": k, **v} if isinstance(v, dict) else {"name": k, "kind": v} for k, v in data.items()] return [FixtureContent.load(item, context) for item in data]public partial class FixtureRoot{ public IList<string> Tags { get; set; } = []; public IDictionary<string, object>? Metadata { get; set; } public IList<FixtureContent> ContentItems { get; set; } = [];
public static IList<FixtureContent> LoadContentItems(object data, LoadContext? context) { var result = new List<FixtureContent>(); foreach (var item in (IEnumerable<object>)data) result.Add(FixtureContent.Load(item.GetDictionary(FixtureContent.ShorthandProperty), context)); return result; }}type FixtureRoot struct { Tags []string `json:"tags" yaml:"tags"` Metadata map[string]interface{} `json:"metadata,omitempty" yaml:"metadata,omitempty"` ContentItems []interface{} `json:"contentItems" yaml:"contentItems"`}
for i, v := range arr { if item, ok := v.(map[string]interface{}); ok { loaded, _ := LoadFixtureContent(item, ctx) result.ContentItems[i] = loaded }}public class FixtureRoot { public List<String> tags = new ArrayList<>(); public Map<String, Object> metadata = null; public List<FixtureContent> contentItems = new ArrayList<>();
if (map.get("contentItems") instanceof Iterable<?> values) { for (Object item : values) { result.contentItems.add(FixtureContent.load(item, ctx)); } }}pub struct FixtureRoot { pub tags: Vec<String>, pub metadata: serde_json::Value, pub content_items: Vec<FixtureContent>,}
content_items: value .get("contentItems") .map(|v| Self::load_content_items(v, ctx)) .unwrap_or_default(),public struct FixtureRoot: TypraModel { public var tags: [String] = [] public var metadata: [String: Any]? = nil public var contentItems: [FixtureContent] = []
public static func load(_ data: Any, context: LoadContext = LoadContext()) throws -> FixtureRoot { let object = try TypraRuntime.object(data, typeName: "FixtureRoot") var instance = FixtureRoot() if let value = object["tags"] { instance.tags = try TypraRuntime.array(value, field: "tags").map { try TypraRuntime.string($0, field: "tags") } } if let value = object["metadata"] { instance.metadata = try TypraRuntime.dictionary(value, field: "metadata") } if let value = object["contentItems"] { instance.contentItems = try TypraRuntime.array(value, field: "contentItems").map { try FixtureContent.load($0, context: context) } } return instance }}{ "properties": { "tags": { "type": "array", "items": "string" }, "metadata": { "type": "record", "value": "unknown", "optional": true }, "contentItems": { "type": "array", "items": "FixtureContent" } }}Review note
Section titled “Review note”Collections are often where target-specific ergonomics differ. Review the generated target page for the runtime you intend to publish, especially around nullability, unknown values, and dictionary value types.