This is a prototype of what a deep cast package might look like.
Simple schema can be defined and used like this:
// Listsconst schema = cast.List(cast.int);
List<dynamic> someList = ....;
// Inferred type is List<String>, runtime reified type is List<String>var typedList = schema.cast(someList); // Mapsconst schema = cast.Map(cast.String, cast.int);
Map<dynamic, dynamic> someMap = ....;
// Inferred type is Map<String, int>, runtime reified type is Map<String, int>var typedMap = schema.cast(someMap);Casts can be applied arbitrarily deep:
// Mapsconst schema = cast.Map(cast.String, cast.List(cast.int));
Map<dynamic, dynamic> someMap = ....;
// Inferred type is Map<String, List<int>>, // runtime reified type is Map<String, List<int>>var typedMap = schema.cast(someMap);
// Inferred type is List<int>, // runtime reified type is List<int>var typedList = typedMap["field"];Complex schemas with different types for different fields can also be defined:
const typed = cast.Keyed<String, dynamic>({
"id": cast.int,
"fields": cast.Keyed({"field1": cast.int, "field2": cast.int}),
"extra1": cast.OneOf(cast.String, cast.List(cast.String)),
"extra2": cast.OneOf(cast.String, cast.List(cast.String)),
});Given structured data matching that schema:
var json =<String, dynamic>{
"id":0,
"fields":<String, dynamic>{"field1":1, "field2":2},
"extra1":"hello",
"extra2":<dynamic>["hello"],
};Applying the cast gives back a deeply cast object of the right type:
Map<String, dynamic> result = typed.cast(json);
Map<String, int> fields = result["fields"]; // Implicit cast will not fail