generating-freezed-models — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited generating-freezed-models (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
Generate immutable data classes, union types, and deep copyWith using Freezed v3.2.x. Complements Dart 3 sealed classes by adding copyWith, ==/hashCode, and JSON serialization via json_serializable.
Because Freezed relies heavily on code generation, ensure your pubspec.yaml is fully configured:
dependencies:
freezed_annotation: ^3.2.5
json_annotation: ^4.11.0 # If mutual conversion with JSON is required
dev_dependencies:
build_runner: ^2.14.1
freezed: ^3.2.5
json_serializable: ^6.13.1 # If mutual conversion with JSON is requiredimport 'package:freezed_annotation/freezed_annotation.dart';
// You MUST declare part files; the name must exactly match the current file
part 'user_model.freezed.dart';
part 'user_model.g.dart'; // If utilizing JSON serialization
// Freezed 3.x: prefer `sealed` modifier for exhaustive pattern matching
@freezed
sealed class UserModel with _$UserModel {
const factory UserModel({
required String id,
required String name,
@Default(18) int age,
@JsonKey(name: 'is_active') @Default(true) bool isActive,
}) = _UserModel;
// Required for JSON serialization
factory UserModel.fromJson(Map<String, Object?> json) =>
_$UserModelFromJson(json);
}After every model change, run dart run build_runner build -d.To add computed properties or methods, add a private parameterless constructor.
@freezed
abstract class Product with _$Product {
// private constructor required to add custom methods
const Product._();
const factory Product({
required double price,
required double discountRate,
}) = _Product;
// Custom Getter
double get discountedPrice => price * (1 - discountRate);
// Custom Method
bool isFree() => discountedPrice == 0;
}@freezed
@JsonSerializable(genericArgumentFactories: true) // required for generic JSON parsing
sealed class PaginatedResponse<T> with _$PaginatedResponse<T> {
const factory PaginatedResponse({
required int currentPage,
required int totalPages,
required List<T> data,
}) = _PaginatedResponse<T>;
// fromJson for generics requires a conversion function parameter
factory PaginatedResponse.fromJson(
Map<String, dynamic> json,
T Function(Object? json) fromJsonT,
) => _$PaginatedResponseFromJson(json, fromJsonT);
}Use Freezed union types for sealed state modeling with automatic subtypes.
@freezed
sealed class ApiResponse with _$ApiResponse {
const factory ApiResponse.loading() = ApiResponseLoading;
const factory ApiResponse.data(List<String> items) = ApiResponseData;
const factory ApiResponse.error(String message) = ApiResponseError;
}Use Dart 3 native pattern matching with Freezed union types:
Widget buildStatus(ApiResponse response) {
return switch (response) {
ApiResponseLoading() => const CircularProgressIndicator(),
ApiResponseData(:final items) => Text('Item Count: ${items.length}'),
ApiResponseError(:final message) => Text('Error: $message'),
};
}Prefer nativeswitchexpressions over.when()/.map()— better compiler exhaustiveness checking.
copyWith) vs @unfreezed#### 6.1 Automatic Deep CopyWith When a Freezed class contains another Freezed class, deep copyWith chaining is generated automatically.
// Instead of: user.copyWith(address: user.address.copyWith(city: 'Taipei'))
final newUser = user.copyWith.address(city: 'Taipei');#### 6.2 When to use @unfreezed
@freezed (immutable).@unfreezed allows mutable fields (user.age = 20) but skips ==/hashCode generation.@JsonKeyUse @JsonKey to customize field serialization:
@JsonKey(includeFromJson: false, includeToJson: false)class MyDateConverter implements JsonConverter<DateTime, String> {
const MyDateConverter();
@override
DateTime fromJson(String json) => DateTime.parse(json.replaceAll('/', '-'));
@override
String toJson(DateTime object) => object.toIso8601String();
}
@freezed
sealed class Event with _$Event {
const factory Event({
@MyDateConverter() required DateTime eventDate,
}) = _Event;
// ... fromJson ...
}const ClassName._()) to enable custom getters/methods.switch expressions instead of .when() / .map().@freezed (immutable); avoid @unfreezed in app state.@JsonSerializable(genericArgumentFactories: true).@unfreezed in app state; use only for mutable form models where deep-copy performance is proven problematic.~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.