Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Best method to convert Lists? #180

Open
mnordine opened this issue Feb 20, 2024 · 6 comments
Open

Best method to convert Lists? #180

mnordine opened this issue Feb 20, 2024 · 6 comments

Comments

@mnordine
Copy link
Contributor

mnordine commented Feb 20, 2024

I'm guessing this isn't a bug, so was more wondering what the recommendation would be with the following:

import 'package:web/web.dart';

Future<void> main() async {
  window.navigator.vibrate([400]);
}

yields error: The argument type 'List<int>' can't be assigned to the parameter type 'JSAny'. (argument_type_not_assignable at [web_test] web/main.dart:4)

It seems Lists of primitives are not automatically handled. Should we:

  • window.navigator.vibrate([400] as VibratePattern);
  • window.navigator.vibrate([400].jsify()!);
  • something else
    ?
@ykmnkmi
Copy link

ykmnkmi commented Feb 21, 2024

You can cast types such as String, num, bool, and List of these values to their JS variants, for example <int>[400] as JSArray.

@srujzs
Copy link
Contributor

srujzs commented Feb 21, 2024

You can cast types such as String, num, bool, and List of these values to their JS variants, for example [400] as JSArray.

Oh no, don't do this! :) This isn't platform-consistent as Lists are not Arrays when compiling to Wasm. I hope to get a lint here: dart-lang/linter#4841. See https://dart.dev/interop/js-interop/js-types#compatibility-type-checks-and-casts for more details.

window.navigator.vibrate([400].jsify()!); will work but might be slower due to type-checks. You have several options (and I should add a tutorial in the docs to make it canonical):

  1. [400.toJS].toJS (convert everything to a JS type while creating the list in the first place - fastest)
  2. [400].map((e) => e.toJS).toList().toJS (convert everything after construction - slower but more flexible, but I hate the syntax)
  3. [400].jsify() as JSArray<JSNumber> (convert everything by iterating and doing type-checks - slowest but probably not much slower than 2 as primitives are fast paths)

For brevity, I prefer 1 and 3, but 2 makes sense in cases where you know that the list is of one type and might be an expensive type to do jsify for. We've considered adding helper functions for 2, but you end up adding a lot of extensions to address every JS type case e.g.

extension on List<int> {
  JSArray<JSNumber> toJS => this.map((e) => e.toJS).toList().toJS();
}

extension on List<String> {
  JSArray<JSNumber> toJS => this.map((e) => e.toJS).toList().toJS();
}

but maybe doing it for just primitives tackles the common case. A downside is that this might encourage slightly slower code like [400, 500, 600].toJS instead of the faster [400.toJS, 500.toJS, 600.toJS].toJS.

Hope that helps!

@mnordine
Copy link
Contributor Author

I had also tried [400.toJS].toJS, but figured there must be a better way.

Btw, anything wrong with

window.navigator.vibrate([400] as VibratePattern);

in this case?

@srujzs
Copy link
Contributor

srujzs commented Feb 21, 2024

Btw, anything wrong with window.navigator.vibrate([400] as VibratePattern); in this case?

Yes, for a similar reason as above around casting Dart types to a JS types (VibratePattern is a typedef for JSAny): it's not platform-consistent.

@ykmnkmi
Copy link

ykmnkmi commented Feb 21, 2024

I use unsafe casts a lot. Encountered that while trying to compile to WASM module.

@srujzs
Copy link
Contributor

srujzs commented Feb 21, 2024

I use unsafe casts a lot. Encountered that while trying to compile to WASM module.

Yeah, and I can totally see why users reach for casts since the language doesn't tell you that isn't okay, which is why I want that lint above.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants