sdkgen icon indicating copy to clipboard operation
sdkgen copied to clipboard

Feature Request (dart-generator): Add `copyWith` method in data classes

Open daniloapr opened this issue 4 years ago • 3 comments

This is feature request is a improvement proposal for adding a copyWith method that would allow changing the ApiClient's objects without depending directly on them.

Example:

class User {
  final String id;
  final String name;

  const User({
    required this.id,
    required this.name,
  });
  
  User copyWith({
    String? id,
    String? name,
  }) {
    return User(
      id: id ?? this.id,
      name: name ?? this.name,
    );
  }
}

Use case:

// get user from api
final user = await apiClient.getUser();

// update user name keeping the id
final updatedUser = user.copyWith(name: 'New Name');
await apiClient.updateUser(newUser);

daniloapr avatar Nov 04 '21 15:11 daniloapr

How does this work if the field itself is nullable and you want to set it to null?

lbguilherme avatar Nov 10 '21 17:11 lbguilherme

Good question! We can use another class to help with that:

class User {
  final String id;
  final String name;
  final String? nickname;

  const User({
    required this.id,
    required this.name,
    this.nickname,
  });
  
  User copyWith({
    Param<String>? id,
    Param<String>? name,
    Param<String?>? nickname,
  }) {
    return User(
      id: id != null ? id.value : this.id,
      name:name != null ? name.value : this.name,
      nickname: nickname != null ? nickname.value : this.nickname,
    );
  }
  
  @override
  String toString() {
    return '''
    id: $id,
    name: $name,
    nickname: $nickname
    ''';
  }
}

class Param<T> {
  final T value;
  
  Param(this.value);
}

daniloapr avatar Nov 10 '21 22:11 daniloapr

Another possible approach, changing only the nullable fields:

class User {
  final String id;
  final String name;
  final String? nickname;

  const User({
    required this.id,
    required this.name,
    this.nickname,
  });
  
  User copyWith({
    String? id,
    String? name,
    Nullable<String?>? nickname,
  }) {
    return User(
      id: id ?? this.id,
      name: name ?? this.name,
      nickname: nickname != null ? nickname.value : this.nickname,
    );
  }
  
  @override
  String toString() {
    return '''
    id: $id,
    name: $name,
    nickname: $nickname
    ''';
  }
}

class Nullable<T> {
  final T value;
  
  Nullable(this.value);
}

daniloapr avatar Nov 17 '21 15:11 daniloapr