library test;
import self as self;
import "dart:core" as core;

typedef Asserter<T extends core::Object = dynamic> = (T) → void;
typedef AsserterBuilder<S extends core::Object = dynamic, T extends core::Object = dynamic> = (S) → (T) → void;
class DartType extends core::Object {
  synthetic constructor •() → self::DartType
    : super core::Object::•()
    ;
}
abstract class C extends core::Object {
  static field (core::List<(self::DartType) → void>) → (self::DartType) → void assertBOf = null;
  field (core::List<(self::DartType) → void>) → (self::DartType) → void assertAOf = null;
  synthetic constructor •() → self::C
    : super core::Object::•()
    ;
  static get assertCOf() → (core::List<(self::DartType) → void>) → (self::DartType) → void
    return null;
  abstract get assertDOf() → (core::List<(self::DartType) → void>) → (self::DartType) → void;
  method method((core::List<(self::DartType) → void>) → (self::DartType) → void assertEOf) → dynamic {
    this.assertAOf(<dynamic>[self::_isInt, self::_isString]);
    self::C::assertBOf.call(<dynamic>[self::_isInt, self::_isString]);
    self::C::assertCOf.call(<dynamic>[self::_isInt, self::_isString]);
    this.{self::C::assertDOf}(<dynamic>[self::_isInt, self::_isString]);
    assertEOf.call(<dynamic>[self::_isInt, self::_isString]);
  }
}
abstract class G<T extends core::Object = dynamic> extends core::Object {
  field (core::List<(self::DartType) → void>) → (self::DartType) → void assertAOf = null;
  synthetic constructor •() → self::G<self::G::T>
    : super core::Object::•()
    ;
  abstract get assertDOf() → (core::List<(self::DartType) → void>) → (self::DartType) → void;
  method method((core::List<(self::DartType) → void>) → (self::DartType) → void assertEOf) → dynamic {
    this.assertAOf(<dynamic>[self::_isInt, self::_isString]);
    this.{self::G::assertAOf}(<dynamic>[self::_isInt, self::_isString]);
    this.{self::G::assertDOf}(<dynamic>[self::_isInt, self::_isString]);
    assertEOf.call(<dynamic>[self::_isInt, self::_isString]);
  }
}
static field (self::DartType) → void _isInt;
static field (self::DartType) → void _isString;
static field (core::List<(self::DartType) → void>) → (self::DartType) → void assertBOf;
static get assertCOf() → (core::List<(self::DartType) → void>) → (self::DartType) → void
  return null;
static method test() → dynamic {
  (core::List<(self::DartType) → void>) → (self::DartType) → void assertAOf;
  assertAOf.call(<dynamic>[self::_isInt, self::_isString]);
  self::assertBOf.call(<dynamic>[self::_isInt, self::_isString]);
  self::assertCOf.call(<dynamic>[self::_isInt, self::_isString]);
  self::C::assertBOf.call(<dynamic>[self::_isInt, self::_isString]);
  self::C::assertCOf.call(<dynamic>[self::_isInt, self::_isString]);
  self::C c;
  c.assertAOf(<dynamic>[self::_isInt, self::_isString]);
  c.assertDOf(<dynamic>[self::_isInt, self::_isString]);
  self::G<core::int> g;
  g.assertAOf(<dynamic>[self::_isInt, self::_isString]);
  g.assertDOf(<dynamic>[self::_isInt, self::_isString]);
}
static method main() → dynamic {}
