dart-lang / sdk

The Dart SDK, including the VM, JS and Wasm compilers, analysis, core libraries, and more.
https://dart.dev
BSD 3-Clause "New" or "Revised" License
10.08k stars 1.56k forks source link

Build issue with js_interop `isA` #56564

Closed arnaud-secondlayer closed 1 week ago

arnaud-secondlayer commented 2 weeks ago

I'm creating a generic function that leverages isA and get a build error when building to javascript. I'm not able to find a solution.

I have the following script:

import 'dart:js_interop';
import 'package:web/web.dart' as web;

bool myIsA<T extends web.Element>(JSAny element) => element.isA<T>();

int main(){
  return 0;
}

There is the build error with dart compile js a.dart:

a.dart:4:61:
Error: Type argument 'T' needs to be an interop 'ExtensionType'.
bool myIsA<T extends web.Element>(JSAny element) => element.isA<T>();
                                                            ^
Error: Compilation failed.
dart --version
Dart SDK version: 3.5.1 (stable) (Tue Aug 13 21:02:17 2024 +0000) on "macos_arm64"
dart-github-bot commented 2 weeks ago

Summary: The user is encountering a build error when using js_interop's isA method with a generic type parameter constrained to web.Element. The error message indicates that the type argument T must be an interop ExtensionType, but the user is unable to find a solution.

sigmundch commented 2 weeks ago

Thanks so much for reaching out. This is a great question!

cc @srujzs

Unfortunately, I don't believe this pattern can be supported.

The way the isA method works, is through a static compiler transformation that needs to see explicitly the actual type passed to it. For example, the list of cases mentioned in the isA API docs are all resolved statically:

e.isA<JSBoolean>()  -- becomes --> typeof e == 'boolean'
e.isA<DivElement>() -- becomes --> instanceof e == 'HTMLDivElement'
...

The pattern you show, where isA gets wrapped in a generic method, makes the instantiation of T happen later at runtime, and as a result the compiler no longer knows what to generate. Note that most information about interop types is erased during compilation, so there is no runtime alternative to achieve the same goal.

One small action item we can do here is to improve the error message and to add a note about this in the API docs.