import 'dart:js_interop';
void main() {
void f(String? s) {
print(s);
}
(f as void Function(String)).toJS.callAsFunction(null, null);
}
DDC and dart2js should print null while dart2wasm will throw. dart2wasm does an explicit conversion of a JS value based on the static type of the function, whereas DDC and dart2js don't require such conversions.
While I'm working on fixing the arity differences to always use the static type's arity, these type checks can't be easily addressed unless we generate a new function for every toJS'd function in dart2js/DDC (which is expensive).
The general advice is that the static type is the source of truth of toJS, and doing such subtyping may lead to slightly different behavior.