Skip to content

feat: let a route declare its result type so pop() and pushForResult<T>() are checked against each other #61

Description

@Mastersam07

There is currently no type relationship between what a route pops and what its caller awaits.

pushForResult<T>(route) declares what the caller expects. pop([Object? result]) declares nothing about what the route produces. Neither is checked against the other:

// compiles cleanly; returns null (or throws) at runtime
router.pop(a string);
final wallet = await router.pushForResult<Wallet>(SelectWalletRoute());

auto_route had pop<T>(result), which at least typed the producing side. Migrating that to kaisel means dropping the only annotation that existed.

Why migrations make this worse, not better

Routes that carry callbacks (onComplete, onClose, onAction) cannot survive as kaisel routes — routes are const value types with props, and a closure field breaks both const-ness and equality. The natural fix is to convert the callback into a popped result. That is the right move, but it means the number of result-carrying routes goes up during migration, on exactly the axis that has no type safety.

In one app this converted 13 routes from callback-carrying to result-returning. Every one of those is now an untyped contract between two files.

run<T> is not a general answer

KaiselModalRoute<T> + run<T> gives a real typed completion contract, but only for modal flows. A plain screen that returns a value — a picker, a filter sheet promoted to a full screen, a confirmation step — has no equivalent.

Suggestion

Let a route declare its own result type:

abstract class KaiselResultRoute<T> extends KaiselRoute {
  const KaiselResultRoute();
}

final class SelectWallet extends AppRoute implements KaiselResultRoute<Wallet> {
  const SelectWallet();
}

Then:

  • pushForResult infers T from the route (router.pushForResult(SelectWallet())Future<Wallet?>),
  • pop can be checked against the top routes declared type.

Failing that, a pop<T>(T result) overload would at least restore parity with auto_route by typing the producing side.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions