Dart
Three projectors, three code-generation conventions for null-safe Dart 3. Dart has no nested-class construct, so in every variant a nested object/enum field hoists to its own top-level sibling declaration.
json_serializable
import { toDart } from "@rhi-zone/fractal-type-ir/dart-json-serializable"
toDart(t(types.object({
id: t(types.string),
name: t(types.string),
email: t(types.string),
age: opt(t(types.integer)),
})), "User")class User {
final String id;
final String name;
final String email;
final int? age;
User({required this.id, required this.name, required this.email, this.age});
factory User.fromJson(Map<String, dynamic> json) => User(
id: json['id'] as String,
name: json['name'] as String,
email: json['email'] as String,
age: json['age'] == null ? null : json['age'] as int,
);
Map<String, dynamic> toJson() => {
'id': id,
'name': name,
'email': email,
if (age != null) 'age': age,
};
}The fromJson/toJson bodies are hand-reproduced inline rather than generated by build_runner — this projector has no codegen pass of its own to hook into, so the output is a standalone, already-working module.
freezed
import { toFreezed } from "@rhi-zone/fractal-type-ir/dart-freezed"
toFreezed(t(types.object({ id: t(types.string) })), "Item")Unlike json_serializable's standalone output, this emits the annotated declaration a real project runs build_runner over — copyWith, deep equality, and JSON (de)serialization all come from freezed's generated mixin, not hand-rolled code:
import 'package:freezed_annotation/freezed_annotation.dart';
part 'item.freezed.dart';
part 'item.g.dart';
@freezed
abstract class Item with _$Item {
const factory Item({
required String id,
}) = _Item;
factory Item.fromJson(Map<String, dynamic> json) => _$ItemFromJson(json);
}built_value
import { toBuiltValue } from "@rhi-zone/fractal-type-ir/dart-built-value"
toBuiltValue(t(types.object({ id: t(types.string) })), "Item")Fields are abstract getters, not constructor parameters — built_value's build.yaml/build_runner pass derives the mutable ItemBuilder from the getter signatures:
import 'package:built_value/built_value.dart';
import 'package:built_value/serializer.dart';
part 'item.g.dart';
abstract class Item implements Built<Item, ItemBuilder> {
String get id;
static Serializer<Item> get serializer => _$itemSerializer;
Item._();
factory Item([void Function(ItemBuilder) updates]) = _$Item;
}