add more type information to the 'webSocketHandler' method (#463)

* [shelf_web_socket] add more type information to the 'webSocketHandler' method

* update docs

* use a dependency_override

* require dart 3.5.0
diff --git a/.github/workflows/dart.yml b/.github/workflows/dart.yml
index 2f060b1..057e8e4 100644
--- a/.github/workflows/dart.yml
+++ b/.github/workflows/dart.yml
@@ -40,16 +40,16 @@
       - name: mono_repo self validate
         run: dart pub global run mono_repo generate --validate
   job_002:
-    name: "analyze_and_format; linux; Dart 3.3.0; PKGS: pkgs/shelf_packages_handler, pkgs/shelf_proxy, pkgs/shelf_router, pkgs/shelf_router_generator, pkgs/shelf_static, pkgs/shelf_test_handler, pkgs/shelf_web_socket; `dart analyze --fatal-infos .`"
+    name: "analyze_and_format; linux; Dart 3.3.0; PKGS: pkgs/shelf_packages_handler, pkgs/shelf_proxy, pkgs/shelf_router, pkgs/shelf_router_generator, pkgs/shelf_static, pkgs/shelf_test_handler; `dart analyze --fatal-infos .`"
     runs-on: ubuntu-latest
     steps:
       - name: Cache Pub hosted dependencies
         uses: actions/cache@6849a6489940f00c2f30c0fb92c6274307ccb58a
         with:
           path: "~/.pub-cache/hosted"
-          key: "os:ubuntu-latest;pub-cache-hosted;sdk:3.3.0;packages:pkgs/shelf_packages_handler-pkgs/shelf_proxy-pkgs/shelf_router-pkgs/shelf_router_generator-pkgs/shelf_static-pkgs/shelf_test_handler-pkgs/shelf_web_socket;commands:analyze"
+          key: "os:ubuntu-latest;pub-cache-hosted;sdk:3.3.0;packages:pkgs/shelf_packages_handler-pkgs/shelf_proxy-pkgs/shelf_router-pkgs/shelf_router_generator-pkgs/shelf_static-pkgs/shelf_test_handler;commands:analyze"
           restore-keys: |
-            os:ubuntu-latest;pub-cache-hosted;sdk:3.3.0;packages:pkgs/shelf_packages_handler-pkgs/shelf_proxy-pkgs/shelf_router-pkgs/shelf_router_generator-pkgs/shelf_static-pkgs/shelf_test_handler-pkgs/shelf_web_socket
+            os:ubuntu-latest;pub-cache-hosted;sdk:3.3.0;packages:pkgs/shelf_packages_handler-pkgs/shelf_proxy-pkgs/shelf_router-pkgs/shelf_router_generator-pkgs/shelf_static-pkgs/shelf_test_handler
             os:ubuntu-latest;pub-cache-hosted;sdk:3.3.0
             os:ubuntu-latest;pub-cache-hosted
             os:ubuntu-latest
@@ -114,15 +114,6 @@
         run: dart analyze --fatal-infos .
         if: "always() && steps.pkgs_shelf_test_handler_pub_upgrade.conclusion == 'success'"
         working-directory: pkgs/shelf_test_handler
-      - id: pkgs_shelf_web_socket_pub_upgrade
-        name: pkgs/shelf_web_socket; dart pub upgrade
-        run: dart pub upgrade
-        if: "always() && steps.checkout.conclusion == 'success'"
-        working-directory: pkgs/shelf_web_socket
-      - name: "pkgs/shelf_web_socket; dart analyze --fatal-infos ."
-        run: dart analyze --fatal-infos .
-        if: "always() && steps.pkgs_shelf_web_socket_pub_upgrade.conclusion == 'success'"
-        working-directory: pkgs/shelf_web_socket
   job_003:
     name: "analyze_and_format; linux; Dart 3.4.0; PKG: pkgs/shelf; `dart analyze --fatal-infos .`"
     runs-on: ubuntu-latest
@@ -154,6 +145,36 @@
         if: "always() && steps.pkgs_shelf_pub_upgrade.conclusion == 'success'"
         working-directory: pkgs/shelf
   job_004:
+    name: "analyze_and_format; linux; Dart 3.5.0; PKG: pkgs/shelf_web_socket; `dart analyze --fatal-infos .`"
+    runs-on: ubuntu-latest
+    steps:
+      - name: Cache Pub hosted dependencies
+        uses: actions/cache@6849a6489940f00c2f30c0fb92c6274307ccb58a
+        with:
+          path: "~/.pub-cache/hosted"
+          key: "os:ubuntu-latest;pub-cache-hosted;sdk:3.5.0;packages:pkgs/shelf_web_socket;commands:analyze"
+          restore-keys: |
+            os:ubuntu-latest;pub-cache-hosted;sdk:3.5.0;packages:pkgs/shelf_web_socket
+            os:ubuntu-latest;pub-cache-hosted;sdk:3.5.0
+            os:ubuntu-latest;pub-cache-hosted
+            os:ubuntu-latest
+      - name: Setup Dart SDK
+        uses: dart-lang/setup-dart@e630b99d28a3b71860378cafdc2a067c71107f94
+        with:
+          sdk: "3.5.0"
+      - id: checkout
+        name: Checkout repository
+        uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
+      - id: pkgs_shelf_web_socket_pub_upgrade
+        name: pkgs/shelf_web_socket; dart pub upgrade
+        run: dart pub upgrade
+        if: "always() && steps.checkout.conclusion == 'success'"
+        working-directory: pkgs/shelf_web_socket
+      - name: "pkgs/shelf_web_socket; dart analyze --fatal-infos ."
+        run: dart analyze --fatal-infos .
+        if: "always() && steps.pkgs_shelf_web_socket_pub_upgrade.conclusion == 'success'"
+        working-directory: pkgs/shelf_web_socket
+  job_005:
     name: "analyze_and_format; linux; Dart dev; PKGS: pkgs/shelf, pkgs/shelf_packages_handler, pkgs/shelf_proxy, pkgs/shelf_router, pkgs/shelf_router_generator, pkgs/shelf_static, pkgs/shelf_test_handler, pkgs/shelf_web_socket; `dart analyze --fatal-infos .`"
     runs-on: ubuntu-latest
     steps:
@@ -246,7 +267,7 @@
         run: dart analyze --fatal-infos .
         if: "always() && steps.pkgs_shelf_web_socket_pub_upgrade.conclusion == 'success'"
         working-directory: pkgs/shelf_web_socket
-  job_005:
+  job_006:
     name: "analyze_and_format; linux; Dart dev; PKGS: pkgs/shelf, pkgs/shelf_packages_handler, pkgs/shelf_proxy, pkgs/shelf_router, pkgs/shelf_router_generator, pkgs/shelf_static, pkgs/shelf_test_handler, pkgs/shelf_web_socket; `dart format --output=none --set-exit-if-changed .`"
     runs-on: ubuntu-latest
     steps:
@@ -339,17 +360,17 @@
         run: "dart format --output=none --set-exit-if-changed ."
         if: "always() && steps.pkgs_shelf_web_socket_pub_upgrade.conclusion == 'success'"
         working-directory: pkgs/shelf_web_socket
-  job_006:
-    name: "unit_test; linux; Dart 3.3.0; PKGS: pkgs/shelf_packages_handler, pkgs/shelf_proxy, pkgs/shelf_router, pkgs/shelf_router_generator, pkgs/shelf_static, pkgs/shelf_test_handler, pkgs/shelf_web_socket; `dart test --test-randomize-ordering-seed=random`"
+  job_007:
+    name: "unit_test; linux; Dart 3.3.0; PKGS: pkgs/shelf_packages_handler, pkgs/shelf_proxy, pkgs/shelf_router, pkgs/shelf_router_generator, pkgs/shelf_static, pkgs/shelf_test_handler; `dart test --test-randomize-ordering-seed=random`"
     runs-on: ubuntu-latest
     steps:
       - name: Cache Pub hosted dependencies
         uses: actions/cache@6849a6489940f00c2f30c0fb92c6274307ccb58a
         with:
           path: "~/.pub-cache/hosted"
-          key: "os:ubuntu-latest;pub-cache-hosted;sdk:3.3.0;packages:pkgs/shelf_packages_handler-pkgs/shelf_proxy-pkgs/shelf_router-pkgs/shelf_router_generator-pkgs/shelf_static-pkgs/shelf_test_handler-pkgs/shelf_web_socket;commands:test_0"
+          key: "os:ubuntu-latest;pub-cache-hosted;sdk:3.3.0;packages:pkgs/shelf_packages_handler-pkgs/shelf_proxy-pkgs/shelf_router-pkgs/shelf_router_generator-pkgs/shelf_static-pkgs/shelf_test_handler;commands:test_0"
           restore-keys: |
-            os:ubuntu-latest;pub-cache-hosted;sdk:3.3.0;packages:pkgs/shelf_packages_handler-pkgs/shelf_proxy-pkgs/shelf_router-pkgs/shelf_router_generator-pkgs/shelf_static-pkgs/shelf_test_handler-pkgs/shelf_web_socket
+            os:ubuntu-latest;pub-cache-hosted;sdk:3.3.0;packages:pkgs/shelf_packages_handler-pkgs/shelf_proxy-pkgs/shelf_router-pkgs/shelf_router_generator-pkgs/shelf_static-pkgs/shelf_test_handler
             os:ubuntu-latest;pub-cache-hosted;sdk:3.3.0
             os:ubuntu-latest;pub-cache-hosted
             os:ubuntu-latest
@@ -414,22 +435,14 @@
         run: "dart test --test-randomize-ordering-seed=random"
         if: "always() && steps.pkgs_shelf_test_handler_pub_upgrade.conclusion == 'success'"
         working-directory: pkgs/shelf_test_handler
-      - id: pkgs_shelf_web_socket_pub_upgrade
-        name: pkgs/shelf_web_socket; dart pub upgrade
-        run: dart pub upgrade
-        if: "always() && steps.checkout.conclusion == 'success'"
-        working-directory: pkgs/shelf_web_socket
-      - name: "pkgs/shelf_web_socket; dart test --test-randomize-ordering-seed=random"
-        run: "dart test --test-randomize-ordering-seed=random"
-        if: "always() && steps.pkgs_shelf_web_socket_pub_upgrade.conclusion == 'success'"
-        working-directory: pkgs/shelf_web_socket
     needs:
       - job_001
       - job_002
       - job_003
       - job_004
       - job_005
-  job_007:
+      - job_006
+  job_008:
     name: "unit_test; linux; Dart 3.3.0; PKG: pkgs/shelf_test_handler; `dart test --test-randomize-ordering-seed=random -p chrome`"
     runs-on: ubuntu-latest
     steps:
@@ -465,7 +478,8 @@
       - job_003
       - job_004
       - job_005
-  job_008:
+      - job_006
+  job_009:
     name: "unit_test; linux; Dart 3.4.0; PKG: pkgs/shelf; `dart test --test-randomize-ordering-seed=random -p chrome`"
     runs-on: ubuntu-latest
     steps:
@@ -501,7 +515,8 @@
       - job_003
       - job_004
       - job_005
-  job_009:
+      - job_006
+  job_010:
     name: "unit_test; linux; Dart 3.4.0; PKG: pkgs/shelf; `dart test --test-randomize-ordering-seed=random`"
     runs-on: ubuntu-latest
     steps:
@@ -537,7 +552,45 @@
       - job_003
       - job_004
       - job_005
-  job_010:
+      - job_006
+  job_011:
+    name: "unit_test; linux; Dart 3.5.0; PKG: pkgs/shelf_web_socket; `dart test --test-randomize-ordering-seed=random`"
+    runs-on: ubuntu-latest
+    steps:
+      - name: Cache Pub hosted dependencies
+        uses: actions/cache@6849a6489940f00c2f30c0fb92c6274307ccb58a
+        with:
+          path: "~/.pub-cache/hosted"
+          key: "os:ubuntu-latest;pub-cache-hosted;sdk:3.5.0;packages:pkgs/shelf_web_socket;commands:test_0"
+          restore-keys: |
+            os:ubuntu-latest;pub-cache-hosted;sdk:3.5.0;packages:pkgs/shelf_web_socket
+            os:ubuntu-latest;pub-cache-hosted;sdk:3.5.0
+            os:ubuntu-latest;pub-cache-hosted
+            os:ubuntu-latest
+      - name: Setup Dart SDK
+        uses: dart-lang/setup-dart@e630b99d28a3b71860378cafdc2a067c71107f94
+        with:
+          sdk: "3.5.0"
+      - id: checkout
+        name: Checkout repository
+        uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
+      - id: pkgs_shelf_web_socket_pub_upgrade
+        name: pkgs/shelf_web_socket; dart pub upgrade
+        run: dart pub upgrade
+        if: "always() && steps.checkout.conclusion == 'success'"
+        working-directory: pkgs/shelf_web_socket
+      - name: "pkgs/shelf_web_socket; dart test --test-randomize-ordering-seed=random"
+        run: "dart test --test-randomize-ordering-seed=random"
+        if: "always() && steps.pkgs_shelf_web_socket_pub_upgrade.conclusion == 'success'"
+        working-directory: pkgs/shelf_web_socket
+    needs:
+      - job_001
+      - job_002
+      - job_003
+      - job_004
+      - job_005
+      - job_006
+  job_012:
     name: "unit_test; linux; Dart dev; PKGS: pkgs/shelf, pkgs/shelf_test_handler; `dart test --test-randomize-ordering-seed=random -p chrome -c dart2wasm`"
     runs-on: ubuntu-latest
     steps:
@@ -582,7 +635,8 @@
       - job_003
       - job_004
       - job_005
-  job_011:
+      - job_006
+  job_013:
     name: "unit_test; linux; Dart dev; PKGS: pkgs/shelf, pkgs/shelf_test_handler; `dart test --test-randomize-ordering-seed=random -p chrome`"
     runs-on: ubuntu-latest
     steps:
@@ -627,7 +681,8 @@
       - job_003
       - job_004
       - job_005
-  job_012:
+      - job_006
+  job_014:
     name: "unit_test; linux; Dart dev; PKGS: pkgs/shelf, pkgs/shelf_packages_handler, pkgs/shelf_proxy, pkgs/shelf_router, pkgs/shelf_router_generator, pkgs/shelf_static, pkgs/shelf_test_handler, pkgs/shelf_web_socket; `dart test --test-randomize-ordering-seed=random`"
     runs-on: ubuntu-latest
     steps:
@@ -726,7 +781,8 @@
       - job_003
       - job_004
       - job_005
-  job_013:
+      - job_006
+  job_015:
     name: "unit_test; linux; Dart dev; PKG: pkgs/shelf_router_generator; `dart test --run-skipped -t presubmit-only`"
     runs-on: ubuntu-latest
     steps:
@@ -762,8 +818,9 @@
       - job_003
       - job_004
       - job_005
-  job_014:
-    name: "unit_test; windows; Dart 3.3.0; PKGS: pkgs/shelf_packages_handler, pkgs/shelf_static, pkgs/shelf_test_handler, pkgs/shelf_web_socket; `dart test --test-randomize-ordering-seed=random`"
+      - job_006
+  job_016:
+    name: "unit_test; windows; Dart 3.3.0; PKGS: pkgs/shelf_packages_handler, pkgs/shelf_static, pkgs/shelf_test_handler; `dart test --test-randomize-ordering-seed=random`"
     runs-on: windows-latest
     steps:
       - name: Setup Dart SDK
@@ -800,22 +857,14 @@
         run: "dart test --test-randomize-ordering-seed=random"
         if: "always() && steps.pkgs_shelf_test_handler_pub_upgrade.conclusion == 'success'"
         working-directory: pkgs/shelf_test_handler
-      - id: pkgs_shelf_web_socket_pub_upgrade
-        name: pkgs/shelf_web_socket; dart pub upgrade
-        run: dart pub upgrade
-        if: "always() && steps.checkout.conclusion == 'success'"
-        working-directory: pkgs/shelf_web_socket
-      - name: "pkgs/shelf_web_socket; dart test --test-randomize-ordering-seed=random"
-        run: "dart test --test-randomize-ordering-seed=random"
-        if: "always() && steps.pkgs_shelf_web_socket_pub_upgrade.conclusion == 'success'"
-        working-directory: pkgs/shelf_web_socket
     needs:
       - job_001
       - job_002
       - job_003
       - job_004
       - job_005
-  job_015:
+      - job_006
+  job_017:
     name: "unit_test; windows; Dart 3.3.0; PKG: pkgs/shelf_test_handler; `dart test --test-randomize-ordering-seed=random -p chrome`"
     runs-on: windows-latest
     steps:
@@ -841,7 +890,8 @@
       - job_003
       - job_004
       - job_005
-  job_016:
+      - job_006
+  job_018:
     name: "unit_test; windows; Dart 3.4.0; PKG: pkgs/shelf; `dart test --test-randomize-ordering-seed=random -p chrome`"
     runs-on: windows-latest
     steps:
@@ -867,7 +917,35 @@
       - job_003
       - job_004
       - job_005
-  job_017:
+      - job_006
+  job_019:
+    name: "unit_test; windows; Dart 3.5.0; PKG: pkgs/shelf_web_socket; `dart test --test-randomize-ordering-seed=random`"
+    runs-on: windows-latest
+    steps:
+      - name: Setup Dart SDK
+        uses: dart-lang/setup-dart@e630b99d28a3b71860378cafdc2a067c71107f94
+        with:
+          sdk: "3.5.0"
+      - id: checkout
+        name: Checkout repository
+        uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
+      - id: pkgs_shelf_web_socket_pub_upgrade
+        name: pkgs/shelf_web_socket; dart pub upgrade
+        run: dart pub upgrade
+        if: "always() && steps.checkout.conclusion == 'success'"
+        working-directory: pkgs/shelf_web_socket
+      - name: "pkgs/shelf_web_socket; dart test --test-randomize-ordering-seed=random"
+        run: "dart test --test-randomize-ordering-seed=random"
+        if: "always() && steps.pkgs_shelf_web_socket_pub_upgrade.conclusion == 'success'"
+        working-directory: pkgs/shelf_web_socket
+    needs:
+      - job_001
+      - job_002
+      - job_003
+      - job_004
+      - job_005
+      - job_006
+  job_020:
     name: "unit_test; windows; Dart dev; PKGS: pkgs/shelf, pkgs/shelf_test_handler; `dart test --test-randomize-ordering-seed=random -p chrome`"
     runs-on: windows-latest
     steps:
@@ -902,7 +980,8 @@
       - job_003
       - job_004
       - job_005
-  job_018:
+      - job_006
+  job_021:
     name: "unit_test; windows; Dart dev; PKGS: pkgs/shelf_packages_handler, pkgs/shelf_static, pkgs/shelf_test_handler, pkgs/shelf_web_socket; `dart test --test-randomize-ordering-seed=random`"
     runs-on: windows-latest
     steps:
@@ -955,3 +1034,4 @@
       - job_003
       - job_004
       - job_005
+      - job_006
diff --git a/pkgs/shelf_test_handler/test/server_test.dart b/pkgs/shelf_test_handler/test/server_test.dart
index 5e3c0e8..d92e85e 100644
--- a/pkgs/shelf_test_handler/test/server_test.dart
+++ b/pkgs/shelf_test_handler/test/server_test.dart
@@ -29,7 +29,7 @@
     addTearDown(server.close);
 
     server.handler.expect('GET', '/',
-        webSocketHandler((WebSocketChannel webSocket) {
+        webSocketHandler((WebSocketChannel webSocket, _) {
       webSocket.sink.add('hello!');
       webSocket.sink.close();
     }));
diff --git a/pkgs/shelf_web_socket/CHANGELOG.md b/pkgs/shelf_web_socket/CHANGELOG.md
index aeff3eb..3948a19 100644
--- a/pkgs/shelf_web_socket/CHANGELOG.md
+++ b/pkgs/shelf_web_socket/CHANGELOG.md
@@ -1,12 +1,43 @@
+## 3.0.0-wip
+
+* **BREAKING:**: Change the signature of the `webSocketHandler` method's
+  `onConnection` callback. Previously this took an untyped function with either
+  one or two parameters. This now requires a `ConnectionCallback`; a typedef
+  taking two parameters. See also https://github.com/dart-lang/shelf/issues/457.
+* Add a API usage example.
+* Require Dart `^3.5.0`.
+
+Note that most clients seeing analysis issues from the above breaking change can
+fix it by adding a second parameter to their callback. So, they would change
+this:
+
+```dart
+webSocketHandler((webSocket) {
+  webSocket.stream.listen((message) {
+    webSocket.sink.add('echo $message');
+  });
+});
+```
+
+to this:
+
+```
+webSocketHandler((webSocket, _) {
+  webSocket.stream.listen((message) {
+    webSocket.sink.add('echo $message');
+  });
+});
+```
+
 ## 2.0.1
 
 * Require Dart `^3.3.0`.
 
 ## 2.0.0
 
-* Require Dart `^3.0.0`.
 * **BREAKING:**: Remove support for hijacking WebSocket requests that are not
   being transported using `dart:io` `Socket`s.
+* Require Dart `^3.0.0`.
 
 ## 1.0.4
 
diff --git a/pkgs/shelf_web_socket/README.md b/pkgs/shelf_web_socket/README.md
index 7105c11..a4854dc 100644
--- a/pkgs/shelf_web_socket/README.md
+++ b/pkgs/shelf_web_socket/README.md
@@ -19,12 +19,11 @@
 ```dart
 import 'package:shelf/shelf_io.dart' as shelf_io;
 import 'package:shelf_web_socket/shelf_web_socket.dart';
-import 'package:web_socket_channel/web_socket_channel.dart';
 
 void main() {
-  var handler = webSocketHandler((webSocket) {
+  var handler = webSocketHandler((webSocket, _) {
     webSocket.stream.listen((message) {
-      webSocket.sink.add("echo $message");
+      webSocket.sink.add('echo $message');
     });
   });
 
diff --git a/pkgs/shelf_web_socket/example/example.dart b/pkgs/shelf_web_socket/example/example.dart
new file mode 100644
index 0000000..44bb9e4
--- /dev/null
+++ b/pkgs/shelf_web_socket/example/example.dart
@@ -0,0 +1,18 @@
+// Copyright (c) 2014, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:shelf/shelf_io.dart' as shelf_io;
+import 'package:shelf_web_socket/shelf_web_socket.dart';
+
+void main() {
+  var handler = webSocketHandler((webSocket, _) {
+    webSocket.stream.listen((message) {
+      webSocket.sink.add('echo $message');
+    });
+  });
+
+  shelf_io.serve(handler, 'localhost', 8080).then((server) {
+    print('Serving at ws://${server.address.host}:${server.port}');
+  });
+}
diff --git a/pkgs/shelf_web_socket/lib/shelf_web_socket.dart b/pkgs/shelf_web_socket/lib/shelf_web_socket.dart
index 18e19e0..c6b0f9b 100644
--- a/pkgs/shelf_web_socket/lib/shelf_web_socket.dart
+++ b/pkgs/shelf_web_socket/lib/shelf_web_socket.dart
@@ -18,12 +18,12 @@
 /// This means that this can be placed first in a [Cascade] and only upgrade
 /// requests will be handled.
 ///
-/// The [onConnection] must take a [WebSocketChannel] as its first argument. It
-/// may also take a string, the [WebSocket subprotocol][], as its second
-/// argument. The subprotocol is determined by looking at the client's
+/// The [onConnection] takes a [WebSocketChannel] as its first argument and a
+/// nullable string, the [WebSocket subprotocol][], as its second argument.
+/// The subprotocol is determined by looking at the client's
 /// `Sec-WebSocket-Protocol` header and selecting the first entry that also
 /// appears in [protocols]. If no subprotocols are shared between the client and
-/// the server, `null` will be passed instead and no subprotocol heaader will be
+/// the server, `null` will be passed instead and no subprotocol header will be
 /// sent to the client which may cause it to disconnect.
 ///
 /// [WebSocket subprotocol]: https://tools.ietf.org/html/rfc6455#section-1.9
@@ -37,18 +37,14 @@
 /// [origin considerations]: https://tools.ietf.org/html/rfc6455#section-10.2
 ///
 /// If [pingInterval] is specified, it will get passed to the created
-/// channel instance, enabling round-trip disconnect detection.
-/// See [WebSocketChannel] for more details.
-Handler webSocketHandler(Function onConnection,
-    {Iterable<String>? protocols,
-    Iterable<String>? allowedOrigins,
-    Duration? pingInterval}) {
-  if (onConnection is! void Function(Never, Never)) {
-    final innerOnConnection = onConnection;
-    // ignore: inference_failure_on_untyped_parameter, avoid_dynamic_calls
-    onConnection = (webSocket, _) => innerOnConnection(webSocket);
-  }
-
+/// channel instance, enabling round-trip disconnect detection. See
+/// [WebSocketChannel] for more details.
+Handler webSocketHandler(
+  ConnectionCallback onConnection, {
+  Iterable<String>? protocols,
+  Iterable<String>? allowedOrigins,
+  Duration? pingInterval,
+}) {
   return WebSocketHandler(
     onConnection,
     protocols?.toSet(),
diff --git a/pkgs/shelf_web_socket/lib/src/web_socket_handler.dart b/pkgs/shelf_web_socket/lib/src/web_socket_handler.dart
index 4c9c5ce..e86010f 100644
--- a/pkgs/shelf_web_socket/lib/src/web_socket_handler.dart
+++ b/pkgs/shelf_web_socket/lib/src/web_socket_handler.dart
@@ -9,10 +9,17 @@
 import 'package:web_socket_channel/io.dart';
 import 'package:web_socket_channel/web_socket_channel.dart';
 
+/// Used by `webSocketHandler` report connections back to callers.
+///
+/// This takes a [WebSocketChannel] as its first argument and an optional
+/// [subprotocol] as its second argument.
+typedef ConnectionCallback = void Function(
+    WebSocketChannel webSocket, String? subprotocol);
+
 /// A class that exposes a handler for upgrading WebSocket requests.
 class WebSocketHandler {
   /// The function to call when a request is upgraded.
-  final Function _onConnection;
+  final ConnectionCallback _onConnection;
 
   /// The set of protocols the user supports, or `null`.
   final Set<String>? _protocols;
@@ -88,7 +95,6 @@
           protocol: protocol, serverSide: true)
         ..pingInterval = _pingInterval;
 
-      // ignore: avoid_dynamic_calls
       _onConnection(IOWebSocketChannel(webSocket), protocol);
     });
   }
diff --git a/pkgs/shelf_web_socket/pubspec.yaml b/pkgs/shelf_web_socket/pubspec.yaml
index af6f48c..3f9a24a 100644
--- a/pkgs/shelf_web_socket/pubspec.yaml
+++ b/pkgs/shelf_web_socket/pubspec.yaml
@@ -1,5 +1,5 @@
 name: shelf_web_socket
-version: 2.0.1
+version: 3.0.0-wip
 description: A shelf handler that wires up a listener for every connection.
 repository: https://github.com/dart-lang/shelf/tree/master/pkgs/shelf_web_socket
 issue_tracker: https://github.com/dart-lang/shelf/issues?q=is%3Aissue+is%3Aopen+label%3Apackage%3Ashelf_web_socket
@@ -9,7 +9,7 @@
   - shelf
 
 environment:
-  sdk: ^3.3.0
+  sdk: ^3.5.0
 
 dependencies:
   shelf: ^1.1.0
@@ -20,3 +20,7 @@
   dart_flutter_team_lints: ^3.0.0
   http: '>=0.13.0 <2.0.0'
   test: ^1.25.2
+
+# TODO(devoncarew): Remove once package:test supports v2+v3 of shelf_web_socket.
+dependency_overrides:
+  test: ^1.25.11
diff --git a/pkgs/shelf_web_socket/test/web_socket_test.dart b/pkgs/shelf_web_socket/test/web_socket_test.dart
index eb8e00b..dbc5878 100644
--- a/pkgs/shelf_web_socket/test/web_socket_test.dart
+++ b/pkgs/shelf_web_socket/test/web_socket_test.dart
@@ -21,8 +21,7 @@
 
 void main() {
   test('can communicate with a dart:io WebSocket client', () async {
-    final server =
-        await shelf_io.serve(webSocketHandler((WebSocketChannel webSocket) {
+    final server = await shelf_io.serve(webSocketHandler((webSocket, _) {
       webSocket.sink.add('hello!');
       webSocket.stream.first.then((request) {
         expect(request, equals('ping'));
@@ -73,8 +72,7 @@
   });
 
   test('handles protocol header without allowed protocols', () async {
-    final server =
-        await shelf_io.serve(webSocketHandler((WebSocketChannel webSocket) {
+    final server = await shelf_io.serve(webSocketHandler((webSocket, _) {
       webSocket.sink.close();
     }), 'localhost', 0);
 
@@ -136,7 +134,7 @@
     late Uri url;
     setUp(() async {
       server = await shelf_io.serve(
-          webSocketHandler((WebSocketChannel webSocket) {
+          webSocketHandler((webSocket, _) {
             webSocket.sink.close();
           }, allowedOrigins: ['pub.dartlang.org', 'GoOgLe.CoM']),
           'localhost',
@@ -177,8 +175,7 @@
 
   // Regression test for issue 21894.
   test('allows a Connection header with multiple values', () async {
-    final server =
-        await shelf_io.serve(webSocketHandler((WebSocketChannel webSocket) {
+    final server = await shelf_io.serve(webSocketHandler((webSocket, _) {
       webSocket.sink.close();
     }), 'localhost', 0);
 
@@ -193,7 +190,7 @@
     late HttpServer server;
     late Uri url;
     setUp(() async {
-      server = await shelf_io.serve(webSocketHandler((_) {
+      server = await shelf_io.serve(webSocketHandler((_, __) {
         fail('should not create a WebSocket');
       }), 'localhost', 0);
       url = Uri.http('localhost:${server.port}', '');