angular icon indicating copy to clipboard operation
angular copied to clipboard

Pipes and generics

Open Aetet opened this issue 6 years ago • 2 comments

Hi. I have pipe for connecting data from redux store:

import 'package:angular/angular.dart';
import 'package:redux/redux.dart';

typedef Selector<K> = dynamic Function(K state);

@Pipe('stateRef', pure: false)
class ConnectPipe<K> extends PipeTransform {
  final Store<K> _store;
  final ChangeDetectorRef _detector;
  final NgZone _zone;

  ConnectPipe(this._store, this._detector, this._zone) {
    _store.onChange.listen((K _) => marker());
  }

  Selector<K> _selector;
  dynamic _innerState;

  dynamic transform(Selector<K> selector) {
    _selector = selector;
    return _innerState = selector(_store.state);
  }

  void marker() {
    final dynamic some = _selector(_store.state);
    if (some != _innerState) {
      _zone.run(_detector.markForCheck);
    }
  }
}

When I try use it with template

<simple
  [a]="numConverter | stateRef">
</simple>

UsersConverter - selector

int numConverter(SimpleState state) => 42;

When compile it I've got error:

[error] The argument type '(SimpleState) → int' can't be assigned to the parameter type '(dynamic) → dynamic'.

As I can see angular template cannot infer K as generic - SimpleState and treat this as dynamic. And I have type mismatch. How to workaround it or how to add generic types to pipes as I can for directiveTypes.

Aetet avatar May 17 '19 12:05 Aetet

@leonsenft @matanlurey @alorenzen ?

Aetet avatar May 24 '19 19:05 Aetet

Sorry for the late reply. There's no support in the framework for instantiating pipes with generics yet.

I can think of two potential workarounds.

  1. Specify type arguments using inheritance. This might be the best option if you're going to need few types.
// No pipe annotation.
abstract class ConnectPipe<K> extends PipeTransform {
  ... // unchanged.
}

@Pipe('intStateRef', pure: false)
class IntConnectPipe extends ConnectPipe<int> {
  IntConnectPipe(...) : super(...);
}
  1. Only pass functions with dynamic parameters to your pipe. If you want, you can add an assert or type check inside the function to retain some type safety.
int numConverter(dynamic state) {
  if (state is SimpleState) {
    ...
  }
}

leonsenft avatar May 24 '19 19:05 leonsenft