Make it easy to use type B in place of type A when there is an obvious/explicit conversion from B -> A
Every place in pkg:http with a url parameter types it as dynamic.
Future<Response> get(url, {Map<String, String> headers}) => ...
void doWork() async {
await get('http://example.com');
await get(Uri.parse('http://example.com'));
await get(42); // statically fine, but causes a runtime error
}
This is to support a common use case: devs often want to pass either Uri
or String to such methods. In the end, all String values are "upgraded"
to Uri before use. To support the desired flexibility, the user risks
runtime errors if something other than String or Uri are provided.
Flutter avoids this issue, by being explicit about types everywhere.
// Flutter
void giveMeABorder(BorderRadiusGeometry value) {}
void doWork() {
giveMeABorder(const BorderRadius.all(
Radius.circular(18),
));
// User would like to write this, but...
giveMeABorder(18); // static error
}
The existing request(s) for union types – https://github.com/dart-lang/sdk/issues/4938 and https://github.com/dart-lang/language/issues/83 – could be an option here, but it would require updating all parameters and setters to specify the supported types.
It'd be nice to be able to define explicit conversions so one could easily pass String to properties/params requiring Uri, etc.
This would be great to have!
Followed this back from #108, which is a possible solution.
I'm wondering if another possible solution would be to support a "where" clause in generic types? So you could define:
Future<Response> get<T where (T is String || T is Uri)>(T uriObj) {
Uri uri = uriObj is Uri ? uriObj : Uri.parse(uriObj);
//....
}
This would allow the linter to check the type of uriObj and warn developers of errors.
A side benefit for extensions would be better controlling the types that are affected by your extension when working with generically typed classes like iterables and comparables.
While 108 would allow for this and solve this issue, it seems to me tha is a larger change to the underlying compiler.
Swift has a similar where function for generic types. https://docs.swift.org/swift-book/documentation/the-swift-programming-language/generics/#Generic-Where-Clauses
Just a thought.
Future<Response> get<T where (T is String || T is Uri)>(T uriObj) { Uri uri = uriObj is Uri ? uriObj : Uri.parse(uriObj); //.... }
Looks very similar to union types (issue #83), but with a much more verbose syntax.