invalid-runtime-check-with-js-interop-types

Same as invalid_runtime_check_with_js_interop_types in Dart lints

Path
lint/correctness/invalid-runtime-check-with-js-interop-types
Default
On (recommended)
Origin
Dart lints
Rule
248 of 512
recommended

Reject platform-dependent runtime checks involving JavaScript interop types.

Invalid

example.dartdart
import 'dart:js_interop';
import 'dart:core';
import 'dart:core' as core;

extension type MyJs(JSObject value) {}
extension type OtherJs(JSObject value) {}

@JS()
@staticInterop
class StaticJs {}

bool dartAgainstJs(Object value) => value is JSObject;
bool jsAgainstDart(JSAny value) => value is String;
bool unrelatedUsers(MyJs value) => value is OtherJs;
String invalidCast(JSAny value) => value as String;
bool anyIsObject(JSAny value) => value is JSObject;
bool nestedGeneric(List<JSAny> value) => value is List<JSObject>;
bool nestedRecord((JSAny,) value) => value is (JSObject,);

void catchesInterop() {
  try {
    throw StateError('x');
  } on JSAny catch (error) {
    error;
  }
}

bool dynamicIsInterop(dynamic value) => value is JSAny;

// Explicit core prefixes exercise SDK-free imported identity resolution too.
void catchesNestedInterop<T extends JSNumber>() {
  try {
    throw StateError('nested');
  } on core.List<JSString> catch (error) {
    error;
  } on core.List<T> catch (error) {
    error;
  }
}
Runtime type checks involving JS interop types are platform-dependent.
11
12bool dartAgainstJs(Object value) => value is JSObject;
Runtime type checks involving JS interop types are platform-dependent.
12bool dartAgainstJs(Object value) => value is JSObject;
13bool jsAgainstDart(JSAny value) => value is String;
Runtime type checks involving JS interop types are platform-dependent.
13bool jsAgainstDart(JSAny value) => value is String;
14bool unrelatedUsers(MyJs value) => value is OtherJs;
This cast between JS interop and Dart types is not portable.
14bool unrelatedUsers(MyJs value) => value is OtherJs;
15String invalidCast(JSAny value) => value as String;
Runtime type checks involving JS interop types are platform-dependent.
15String invalidCast(JSAny value) => value as String;
16bool anyIsObject(JSAny value) => value is JSObject;
Runtime type checks involving JS interop types are platform-dependent.
16bool anyIsObject(JSAny value) => value is JSObject;
17bool nestedGeneric(List<JSAny> value) => value is List<JSObject>;
Runtime type checks involving JS interop types are platform-dependent.
17bool nestedGeneric(List<JSAny> value) => value is List<JSObject>;
18bool nestedRecord((JSAny,) value) => value is (JSObject,);
JS interop types cannot be used as catch types.
22 throw StateError('x');
23 } on JSAny catch (error) {
Runtime type checks involving JS interop types are platform-dependent.
27
28bool dynamicIsInterop(dynamic value) => value is JSAny;
JS interop types cannot be used as catch types.
33 throw StateError('nested');
34 } on core.List<JSString> catch (error) {
JS interop types cannot be used as catch types.
35 error;
36 } on core.List<T> catch (error) {

Valid

example.dartdart
import 'dart:js_interop';

extension type MyJs(JSObject value) {}

bool sameSdk(JSAny value) => value is JSAny;
bool sdkSubtype(JSArray<JSAny> value) => value is JSObject;
bool typedArraySubtype(JSUint8Array value) => value is JSObject;
bool sameUser(MyJs value) => value is MyJs;
bool nestedSubtype(List<JSArray<JSAny>> value) => value is List<JSObject>;
bool functionParameterSubtype(void Function(JSAny) value) =>
    value is void Function(JSObject);
bool functionReturnSubtype(JSObject Function() value) =>
    value is JSAny Function();
bool ordinary(Object value) => value is String;
JSAny objectAsAny(Object value) => value as JSAny;
JSObject anyAsObject(JSAny value) => value as JSObject;
Object dynamicSource(dynamic value) => value as JSAny;

// The analyzer's `canBeSubtypeOf` never descends into function types.
bool functionParameterWrongDirection(void Function(JSObject) value) =>
    value is void Function(JSAny);
bool functionReturnWrongDirection(JSAny Function() value) =>
    value is JSObject Function();

// Null normalizes to Never, so it does not trigger an interop runtime lint.
bool nullIsInterop() => null is JSAny;
JSAny nullAsInterop() => null as JSAny;

void catchesOrdinary() {
  try {
    throw StateError('ordinary');
  } on List<String> catch (error) {
    error;
  }
}

Configure invalid-runtime-check-with-js-interop-types

Set its severity in falcon.json. See the configuration guide.

falcon.jsonjson
{
  "linter": {
    "rules": {
      "correctness": {
        "invalid-runtime-check-with-js-interop-types": "error"
      }
    }
  }
}

Or silence one occurrence with a suppression comment; the reason is required.

example.dartdart
// falcon-ignore lint/correctness/invalid-runtime-check-with-js-interop-types: <reason>
  • library-private-types-in-public-apilibrary_private_types_in_public_apirecommended

    Avoid using library-private types in public APIs.

  • list-all-equatable-fieldsrecommendedequatable

    Flags declared instance fields omitted from a statically understood Equatable props list.

  • literal-only-boolean-expressionsliteral_only_boolean_expressionsrecommended

    Flags conditions built only from literals, whose value never changes.

  • match-getter-setter-field-names

    Detect likely copy-paste errors in trivial accessors when a different field matching the accessor name is declared.

  • missing-test-assertionrecommendedtest

    Reports inline test callbacks that contain no recognized assertion calls.

  • no-adjacent-strings-in-listno_adjacent_strings_in_listrecommended

    Flags adjacent string literals used as an element of a list or set literal.

  • no-import-cyclescross-file

    Report mutually dependent components of imported or exported library files.

  • no-logic-in-create-stateno_logic_in_create_staterecommendedflutter

    Require StatefulWidget.createState to return only a fresh zero-argument Flutter State construction.