-
Notifications
You must be signed in to change notification settings - Fork 205
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
Add possibility to consistently get object property name #251
Comments
Considering that you can't use this information (i.e. there is no reflective support), what would this accomplish? |
You can use it in It's a good idea. The current symbol literals are stupid - they're basically shorthands for strings, there is no relation to the identifier you actually want to match. That makes typos hard to detect and refactoring impossible to automate. Example: abstract class Foo {
int bar();
}
class MockFoo implements Foo {
noSuchMethod(i) {
if (i.memberName == #baar) return 42; // Whoops
return super.noSuchMethod(i);
}
} I wouldn't use a macro like We can't use import "self.dart" as self;
abstract class C {
static foo({bar});
baz({qux});
get toto;
}
main() {
var c = ##C;
var cFoo = ##C.foo;
var cFooBar = ##C.foo.bar; // maybe.
var cFooBar2 = ##self.C.foo.bar;
print(identical(cFooBar, cFooBar2)); // true, yey!
// var wrong = ##C.biff; // Invalid, no biff declared in C.
} and class MockFoo implements Foo {
noSuchMethod(i) {
if (i.memberName == ##Foo.bar) return 42;
// or just `== ##bar`, using the dynamic this-scope since "bar" isn't otherwise in scope.
return super.noSuchMethod(i);
}
} Other possible, but probably too odd, syntaxes: See also #30518, |
@matanlurey |
At least for that particular API, we decided it was probably wrong. I don't know if I'd push for a language feature to fix the API we created (personally). |
There are many places where using symbols is just making life harder for yourself, but they are still useful in a few places ( The language feature by itself makes sense. Whether it carries its own weight, and whether it is worth prioritizing over other language features, are different questions. |
In our big project. Main priority is code support. We have 'toName', 'toSymbol' an analog of nameof. It is made using a transformer and the special code for run vm test.
Interface
All this is directed to ensure that the code is connected at all parts. Developers should receive a real "Find usages". Developers should safely refactor the code. Also in our company, literals are forbidden. Since literals are potential errors. |
this would help me so much. All my models are like:
would be amazing to do something like:
|
@lrhn @munificent @leafpetersen – is this more of a language request? I've been hitting this a lot in the last few days – would make a lot of folks very happy! |
Yes, this sounds like a language request to me. Want to move it over to the language repo? |
Sure! |
I guess the desired guarantee here (cf. the C# nameof) would be that a given symbol corresponding to a single identifier or operator does in fact exist as the name of a declared member of some type. If we make this a built-in property of certain symbols (say, by spelling them as But that's a rather weak guarantee. So maybe the following would be more practical: main() {
const s1 = memberSymbol<A>(#foo); // OK, s1 gets the value `#foo`.
var s2 = memberSymbol<B>(#bar); // OK, memberSymbol(...) is always const.
var s2 = memberSymbol<B>(#foo); // OK, `foo` is in the interface of `B`.
var s3 = memberSymbol<B>(#baz, staticMember: true); // OK.
var s4 = memberSymbol<A>(#qux); // Compile-time error.
memberSymbol(#s1); // Error, refuses to infer a type argument, and `s1` not a member.
}
abstract class A {
foo();
Symbol get test => memberSymbol(#foo); // OK, type argument `A` inferred.
}
class B extends /*or implements, or mixes in*/ A {
int get bar => 42;
static void baz() {}
} This would allow implementations of The We could extend this idea slightly to allow for an optional argument We could of course also consider checking other symbols at compile-time ( |
Any news guys? |
I'd say that this request is still open, and seems to have some level of support, but there are a lot of higher priority things occupying both the language team and the implementation teams right now, so I don't expect this to bubble to the top of the queue in the short term. |
The C# The following example is not trying to prove the benefit, it just shows a use case for a minimal implementation of
I'm trying to create a library for Flutter. Without |
+1 to this, just couple days into Flutter + Firestore started looking for this |
Maybe an alternate solution is to create a new lint rule that warns when a symbol's name doesn't match any variable available? |
There can be a problem with code minification. Imagine we have client-server app, client and server are both on dart. We also have some shared code that used by both. Shared code: class SomeModel {
final name;
SomeModel.fromMap(map):
name = map[nameof(name)];
toMap() => {
nameof(name): name
};
} Flutter web application built in release will not be able to deserialize code serialized by Server and vice versa. Client's toMap will produce map { "mF": "some name" } Server's toMap will produce map {"name": "some name"} Because type and field names are minified in flutter web, but not minified in server. Even when the actual code is the same. Code like |
map[nameof(obj.propertyName)] = SomeData();
* * *
final data = map[nameof(obj.propertyName)]; |
Fwiw, this would be nice for the new Restorable API in flutter, so we don't need to constantly repeat ourselves:
Would be nice to just pass null, and have it internally use nameof(). Also prevents magic string bugs, so its actually better and more robust this way, and works better with refactoring. The id in this case is a string that is supposed to be unique within the scope of a class, which is of course accomplished by just using it's property name; |
Right, thanks for the correction. The longer method is still preferred as it's avoids the magic strings and lets the compiler keep the names in sync. |
Another real world use case we came across, We're trying to come up with some concise method of re-using state in a StatelessWidget in Flutter. Landed on an API that needs a unique-in-scope string, very similar to Restoration:
I think |
Another use case which was not yet mentioned is throwing exceptions that include the parameter name:
|
Wouldn't nameof() be resolved before any minification, so property names would still match the keys in the serialized data? |
before minification would make it to be a const string, minification wouldn't take affect on that. |
A class LoginModelProblemDetails {
final List<String>? account;
final List<String>? password;
final List<String>? accountType;
LoginModelProblemDetails({
this.account,
this.password,
this.accountType,
});
bool hasAnyError(){
return account?.isNotEmpty == true || password?.isNotEmpty == true || accountType?.isNotEmpty == true;
}
bool hasError(String fieldName){
switch(fieldName){
case "account":
return account?.isNotEmpty == true;
case "password":
return password?.isNotEmpty == true;
case "accountType":
return accountType?.isNotEmpty == true;
default:
return false;
}
} If I can use class LoginModelProblemDetails {
final List<String>? account;
final List<String>? password;
final List<String>? accountType;
LoginModelProblemDetails({
this.account,
this.password,
this.accountType,
});
bool hasAnyError(){
return account?.isNotEmpty == true || password?.isNotEmpty == true || accountType?.isNotEmpty == true;
}
bool hasError(String fieldName){
switch(fieldName){
case nameof(account):
return account?.isNotEmpty == true;
case nameof(password):
return password?.isNotEmpty == true;
case nameof(accountType):
return accountType?.isNotEmpty == true;
default:
return false;
}
} check it: final problemDetails = LoginModelProblemDetails.fronJson(jsonDecode('{"title":"validation error","errors":{"account":["Account is required."],"password":["Passowrd is required"]}} '));
print(problemDetails.hasError(nameof(account)); I have a lot of models |
+1 for nameof() equivalent that is 'resolved' before minification currently we create manualy some static const that matches property names... but error can easily occurs if const value is not spelled exactly as the property |
We need to get object property name in cases like Angular 2 ngOnChanges (when you need to compare key from changes map with object property name):
ngOnChanges(Map<String, SimpleChange> changes);
It would be great to have something like nameof in C#, so that we could get property name and don't be afraid that someone will rename property.
nameof(obj.propertyName); // 'propertyName'
The text was updated successfully, but these errors were encountered: