-
-
Notifications
You must be signed in to change notification settings - Fork 250
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Non-constant default values #64
Comments
Dart only supports constant default values. Are you looking for |
Ah, I see what you're speaking of. What about such syntax? @freezed
abstract class SuperLate with _$SuperLate {
factory SuperLate([int value]) = _SuperLate;
@late
@override
int get value => super.value ?? Random().nextInt(9999);
} |
Yes, that would be great! The |
We'll probably need an alternate syntax for unions too: @freezed
abstract class SuperLate with _$SuperLate {
factory SuperLate([@MyDefault() int value]) = _SuperLate;
factory SuperLate.emoty() = _SuperLate;
}
class MyDefault implements Default<T> {
const MyDefault();
T get defaultValue => Random().nextInt(9999);
} Kinda verbose though. |
It matched Json converter template (in a sense that is good). If this gets done, does this mean, we could have default non literals also ? |
Hi @rrousselGit.
|
This is not implemented. Just a thought |
@rrousselGit Could this thought came to reality? I got into the same problem when I want to set empty list to a some field, but I can't get it generified in the
|
Another way to implement this would be to allow a function as Other _defaultOther() => Other();
@freezed
abstract class Example with _$Example {
factory Example(@Default(_defaultOther) Other value) = _Example;
} |
The problem is, people will most likely want to initialize some parameters based on other parameters |
Yeah, probably the most common scenario. But it may solve issues with json serializable : For example : @freezed
abstract class Other with _$Other {
const factory Other() = _Other;
factory Example.fromJson(Map<String, dynamic> json) => _$ExampleFromJson(json);
}
@freezed
abstract class Example with _$Example {
const factory Example(@Default(const Other()) Other value) = _Example;
factory Example.fromJson(Map<String, dynamic> json) => _$ExampleFromJson(json);
} That produces this error :
I'm clueless on how to achieve this right now. |
Another common use case that doesn't need other properties : Example({
DateTime timestamp,
}) : timestamp = timestamp ?? DateTime.now().add(Duration(days: -30)); The nearest approach I found (though the value isn't initialized at instantiation, but at first read): factory Example({
@JsonKey(name: 'timestamp') DateTime optionalTimestamp,
}) = _Example;
@late
DateTime get timestamp =>
optionalTimestamp ??
DateTime.now().add(Duration(days: -30)); |
I understand your concern, but I feel like it's a way to eagerly address future problems, since there hasn't been such feature request until now, as far as I could evaluate. I must add that I cannot really find a good use of such functionality. Default values that depend on different parameters are something other than just default values. I cannot find a good reason to make it easy embracing bad practices. On the other hand, I cannot see how this would play with json_serializable's default value. |
@aloisdeniel If we got to that point, why not creating a dummy private constructor and a second one with body, which allows us to define a default value? const factory Example._(DateTime timestamp) = _Example;
factory Example({
DateTime timestamp,
}) => Example._(timestamp ?? DateTime.now().add(Duration(days: -30))); Notice that the parameter is not optional in the dummy constructor. This is a very important detail. By making it optional, freezed would not generate |
Not if you mark the parameter as |
@hcbpassos Yes absolutely, it is another valid solution, but I wanted to keep the |
Any progress on this? I would like to see this functionality because in a truly null safe app I need default values when I read from the database. It would be awesome to have these default constructors. |
I'm not sure I understand. Do you want a const constructor with non-const default values? |
I have kind of the same issue, don't focus on the logic i was just trying to test forms with riverpod state notifier and freeezed, but I'm not able to continue because DateTime doesn't have a const constructor so I'm thinking is there a possibility to do it or i just need to make a workaround for it? Im also using Formz package for fields @freezed
class LoginState with _$LoginState {
factory LoginState({
@Default(Email.pure()) Email email,
@Default(Password.pure()) Password password,
@Default(DateTime()) Date date,
@Default(FormzStatus.pure) FormzStatus status,
}) = _LoginState;
}
|
Is there another proposed solution to use another freezed class as a default value? Like a default value for a subclass? |
I have the same problem when i want to put an model default value: @freezed
class User with _$User {
const factory User(
{required String id,
required String email,
required String username,
@Default(Profile.empty) Profile profile,}) = _User;
factory User.fromJson(Map<String, dynamic> json) => _$UserFromJson(json);
static const empty = User(
id: '',
email: 'name@dummy.com',
username: 'DummyName',);
} Where [SEVERE] json_serializable:json_serializable on lib/features/user/domain/user.entity.dart:
Error with `@JsonKey` on `profile`. `defaultValue` is `_$_Profile`, it must be a literal.
package:thesis_cancer/features/user/domain/user.entity.freezed.dart:297:17
╷
297 │ final Profile profile;
│ ^^^^^^^
╵
[INFO] Running build completed, took 4.6s
[INFO] Caching finalized dependency graph...
[INFO] Caching finalized dependency graph completed, took 80ms
[SEVERE] Failed after 4.7s
pub finished with exit code 1 |
What about cases with default list value? Like this: class Account with _$Account {
factory Account({
String name,
@Default([]) List<String> photos, //<--- this is not working
}) = _Account;
} I just want to init empty list and don't want to use null. How to do that? |
@rodion-m you can't use implicit-cast for your default value, instead give your empty list a proper type: @Default(<String>[]) List<String> photos, |
Thank you, it works! |
@Default(Set<String>.unmodifiable(<String>[])) Set<String> photos; any idea how i can map the above code on a Set? with this code, i do get The constructor being called isn't a const constructor... |
Instead do: @Default(<String>{}) |
@rrousselGit Hey. Do you have plans in the near future to solve this? It's been a few months now |
No. Feel free to make a pull request |
@rrousselGit As soon as I am able to wrap my head around the Dart build system, I'd love to. BTW your efforts, and that of the community, is well appreciated. I'd love to donate to this project to keep it alive even if all I can afford is a few bucks :D |
Hey @sdebruyn, could you please provide a code example for your workaround? I have a similar use case where I need a random UUID as default value but didn't find a workaround with freezed yet. |
I'm interested in it too. |
The way that this was solved in build value by David Morgan was to identify a static function with a attribute that would be called to perform the defaulting.
|
how to assign a default datetime @freezed
class Client with _$Client {
factory Client({
required User user,
@Default(DateTime.now()) DateTime addedDate, //The constructor being called isn't a const constructor.
Try removing 'const' from the constructor invocation.
}) = _Client;
@late
@override
factory Client.fromJson(Map<String, dynamic> json) => _$ClientFromJson(json);
}
|
Does that suppose to work? got this message |
Uhh, I miss Typescript! Too much work for union types! |
I resolved like this. typedef UUID = String;
@freezed
class SendData with _$SendData {
factory SendData.def({
required String receiver_id,
required List<FileData> files,
required UUID uuid,
}) = _SendData;
factory SendData({
required String receiver_id,
required List<FileData> files,
}) {
return _SendData(
receiver_id: receiver_id,
files: files,
uuid: _generateUuid(),
);
}
static UUID _generateUuid() {
final uuid = Uuid();
return uuid.v4();
}
}
final sendData = SendData(receiver_id: receiver_id, files: files); |
Any progress on this? #64 (comment) |
I have problem with this and DateTime, i have to make that fields nullable by default instead of DateTime.now() lol: DateTime? metricsDateFrom,
DateTime? metricsDateTo, |
Thank you for the 0.7.0 update, the default values made my code a little bit simpler :)
One thing that I still have to work around are non-constant default values. My type has a
String
property calledid
that - if left empty - should have a random UUID value by default. I now work around this by adding a second factory method that redirects to the generated one without theid
parameter.It would be nice if the
@Default
annotation could also take in a lambda to generate the default value.The text was updated successfully, but these errors were encountered: