Skip to content
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

Object spread like TypeScript has #1781

Open
petrnymsa opened this issue Aug 6, 2021 · 2 comments
Open

Object spread like TypeScript has #1781

petrnymsa opened this issue Aug 6, 2021 · 2 comments
Labels
feature Proposed language feature that solves one or more problems

Comments

@petrnymsa
Copy link

Is there any chance to be able to spread objects like we can in TypeScript?

Consider following interface in TS (code simplified)

interface Props {
  a: number;
  b: number;
  c: number;
}

and React component A which accepts these Props

const componentA(props: Props) => <p>A is {props.a}> <ComponentB {...props} /> </p>

where ComponentB defines its props like

interface Props {
  b:number;
  c:number;
}

Why to have similar feature in Dart?

In Flutter especially, if we compose custom widgets I've finding myself many times passing around same arguments to nested widgets. Maintainance of such widgets becomes very troublesome.

Another significant added value is for mapping between objects like from DTO to Domain Entity where Domain Entity typically have nearly same properties + added functionality.

If such issue already exists, feel free to close it. I couldn't find it.

@petrnymsa petrnymsa added the feature Proposed language feature that solves one or more problems label Aug 6, 2021
@Levi-Lesches
Copy link

Just to be clear, does the Dart equivalent to what you're asking look something like this:

class A {
  String prop1; 
  int prop2; 
  bool prop3;
  A({required this.prop1, required this.prop2, required this.prop3});
}

class B {
  String prop1; 
  int prop2;
  B({required this.prop1, required this.prop2});
}

void main() {
  A a = A(prop1: "Hello World", prop2: 42, prop3: true); 
  B b1 = B(...a);  
  // equal to:
  B b2 = B(prop1: a.prop1, prop2: a.prop2);
}

Couple of notes:

  • B would have to have a fully named constructor, because A doesn't have an implicit "order"
  • This would only work with members of A that match the names and types of B's constructor's parameters
  • What should we do if B's constructor has a parameter that A has no field for?
  • This is probably one of those situations where inheritance makes more sense:
class A {
  String prop1; 
  int prop2; 
  bool prop3;
  A({required this.prop1, required this.prop2, required this.prop3});
}

class B extends A {
  bool prop3;
  B({required String prop1, required int prop2, required this.prop3}) : 
    super(prop1: prop1, prop2: prop2);
}

You may be interested in a proposal at #493 that reduces the above to:

class B extends A {
  bool prop3;
  B({required super.prop1, required super.prop2, required this.prop3});
}

This doesn't make it easier for someone who has an A to convert it to a B, like you request, but it makes it easier for someone to write a B that inherits the same features as an A.

@lrhn
Copy link
Member

lrhn commented Aug 7, 2021

This sounds remarkably close to reflection. Reflection is easy in JavaScript because objects are really just maps. That's not the case in Dart. Iterating over the names and values of "properties" in Dart is more complicated. You cannot create an object simply from its property values, you need to go through a constructor. You cannot access properties given just their name. And you cannot iterate the properties of an object to begin with because that's reflection, and it will prevent tree-shaking properties that aren't used in the program (which our AoT compilers try to do).
Here, you have a type, which means that the properties are statically know (I assume), so we could probably do something for each property of the type (each public getter), but that sounds like a job for metaprogramming/macros, not a language feature. Blindly iterating is a fragile construction, if the class you iterate adds another property (say, a Point with an x and y property also adds a distanceToOrigo getter), then your iteration changes.
You'd have more control using pattern matching like Prop{a: var a, b: var b} = prop; return Prop2(a: a, b: b). You do need to repeat the names more, but I generally oppose implicitly naming things.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature Proposed language feature that solves one or more problems
Projects
None yet
Development

No branches or pull requests

3 participants