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

Nested typedefs #2952

Open
jtmcdole opened this issue Mar 11, 2014 · 15 comments
Open

Nested typedefs #2952

jtmcdole opened this issue Mar 11, 2014 · 15 comments
Labels
request Requests to resolve a particular developer problem

Comments

@jtmcdole
Copy link

jtmcdole commented Mar 11, 2014

Currently typedef can only appear at the toplevel. If I have a class that I want to allow a user supplied callback and maintain type checking, there currently is no way:

class Foo<T> {
  Function _callback;
  Foo(void callback(T something)) : this._callback = callback;

  doSomething() {
    ... something ...
    _callback(result);
  }
}
@kasperl
Copy link

kasperl commented Mar 12, 2014

Added Area-Language, Triaged labels.

@gbracha
Copy link

gbracha commented Aug 26, 2014

Our need for typedefs stems from issues around the function type syntax. We can't support anonymous function types very well, which leads to these problems. One can work around them with generic typedefs though.

typedef void Callback<S> (S s);

class Foo<T> {
  Callback<T> _callback;
  Foo(this._callback);
  ...
}

Set owner to @gbracha.
Added Accepted label.

@eseidelGoogle
Copy link

Presumably this is still an issue, but not actively being worked on. :)

I came across this looking for an issue on how to make a typedef for a specialized generic, like Map<String, Map<string, dynamic>, etc (which I believe is currently impossible in Dart, but likely to be a more common request in strong mode). Presumably that's not this bug?

e.g. https://dartpad.dartlang.org/31438e9a6ac9d097c3b6642f66abf935

@bwilkerson
Copy link
Member

I'm not sure, but issue dart-lang/sdk#27527 might be related to your need.

@fsc8000
Copy link

fsc8000 commented Dec 2, 2016

@eseidelGoogle Yes, currently typedef is limited to function types. I agree, there seems no reason why it should not work for arbitrary type aliases. And there is actually an old issue for this: dart-lang/sdk#2626

@munificent
Copy link
Member

This is still an issue, but is a different one from what you describe. This one is about allowing typedef to occur inside a class body.

@lrhn
Copy link
Member

lrhn commented Jun 22, 2018

I still see no reason to prohibit local typedefs, but the new function type syntax allows you to write function types directly so you don't need a typedef to write a function type.

@zoechi
Copy link

zoechi commented Jun 22, 2018

I find inline function types make code hard to read. I prefer typedefs.

@eernstg
Copy link
Member

eernstg commented Jun 22, 2018

The other use case for local typedefs that we have discussed involves type variables:

class Thing<A, B, C> {
  typedef Factory = Thing<A, B, C> Function({A a, B b, List<C> cs = []});

  // `Factory` used many times.
}

A global typedef could be used instead, but it would require writing something like ThingFactory<A, B, C> everywhere inside class Thing (and renaming Factory to ThingFactory seems reasonable, because we are adding a name to the library scope, i.e., to a much more widely seen namespace).

It's definitely possible to argue that this abbreviation is a good thing or that it is a bad thing, but if we decide to support allowing all types (not just function types) on the right hand side of a global typedef then local typedefs seem relevant as well, because they are both about abbreviation of unwieldy type expressions.

@mit-mit
Copy link
Member

mit-mit commented Oct 8, 2021

Completed via #65

@mit-mit mit-mit closed this as completed Oct 8, 2021
@mraleph
Copy link
Member

mraleph commented Oct 8, 2021

@mit-mit I think this is incorrect. This issue is about allowing typedefs to be define within classes - I don't think we have ever done this. The corresponding language issue is #67

@lrhn lrhn reopened this Oct 8, 2021
@mit-mit
Copy link
Member

mit-mit commented Oct 11, 2021

This issue is about allowing typedefs to be define within classes

Got it, thanks

@mit-mit mit-mit changed the title Allow typedef in classes - capture generic type information Nested typedefs Oct 11, 2021
@mit-mit
Copy link
Member

mit-mit commented Oct 11, 2021

Related issue for nested classes: #336

@lrhn
Copy link
Member

lrhn commented Oct 11, 2021

Nested typedefs are slightly simpler than nested classes because typedefs won't introduce a new namespace level.
Even if we end up choosing to not allow nested classes, I'd still be interested in nested typedefs (or, heck, local typedefs declared inside functions).

@eernstg eernstg transferred this issue from dart-lang/sdk Mar 28, 2023
@lrhn lrhn added the request Requests to resolve a particular developer problem label Apr 2, 2023
@lrhn
Copy link
Member

lrhn commented Apr 2, 2023

... and with generalized type aliases, the above comment is no longer correct.

We allow accessing static members through a type alias for a class type (as long as the type alias precisely that class type),
which means that allowing publicly accessible nested type aliases will effectively grant nested namespaces:

abstract final class _NameSpace2 {
  static final int x = 42;
}
abstract final class ns1 {
  static final int x = 37;
  typedef ns2 = _NameSpace2;
}
void main() {
 print(ns1.x);
 print(ns1.ns2.x); // Works?
}

On way to avoid that is to make "local" type alias declaration not become part of the external scope.
Like (but opposite) constructors that are only accessible as ClassName.name, not just name through the lexical scope,
a typedef declaration inside another declaration would only be accessible through the lexical scope, not as OuterScope.aliasName. It's a local declaration, not a publicly visible one.

Another approach would be to allow declarations to nest. You'd have to write static on all the nested declarations of a class, to show that they're part of its namespace, not its instance content, but we could also introduce a plain namespace declaration where all members are implicitly "static". (It's the "zero, one or an infinite amount of any feature" issue, and we're currently at "1" namespace depth. Not counting import prefixes.).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
request Requests to resolve a particular developer problem
Projects
None yet
Development

No branches or pull requests