oxc-project/oxc · warning · OxcDiagnostic

Do not use `instanceof` with built-in constructors

Error message

Do not use `instanceof` with built-in constructors

What it means

Diagnostic from the oxlint rule `unicorn/no-instanceof-builtins` (category: suspicious). `instanceof` against built-in constructors breaks across realms (iframes, workers, Node vm) and misleads for boxed primitives: `'x' instanceof String` is false while `new String('x') instanceof String` is true. Default ('loose') strategy flags Array (suggests `Array.isArray`), Function (suggests `typeof x === 'function'`), the primitive wrappers String/Number/Boolean/BigInt/Symbol (suggests `typeof`), and — when `useErrorIsError` is enabled — Error (suggests `Error.isError()`). The `strict` strategy additionally flags Error subtypes, Map/Set/WeakMap/WeakSet/WeakRef, typed arrays, Object, RegExp, Promise, Proxy, DataView, Date, and more; `include`/`exclude` tune the set. Most suggestions are auto-fixable.

Source

Thrown at crates/oxc_linter/src/rules/unicorn/no_instanceof_builtins.rs:13

use oxc_ast::{AstKind, ast::Expression};
use oxc_diagnostics::OxcDiagnostic;
use oxc_macros::declare_oxc_lint;
use oxc_span::{GetSpan, Span};
use oxc_syntax::operator::BinaryOperator;
use schemars::JsonSchema;
use serde::Serialize;
use serde_json::Value;

use crate::{AstNode, context::LintContext, rule::Rule};

fn no_instanceof_builtins_diagnostic(span: Span) -> OxcDiagnostic {
    OxcDiagnostic::warn("Do not use `instanceof` with built-in constructors")
        .with_help(
            "Use `Array.isArray(…)`, `typeof … === 'string'`, \
             or another realm-safe alternative instead",
        )
        .with_label(span)
}

const PRIMITIVE_WRAPPERS: &[&str] = &["String", "Number", "Boolean", "BigInt", "Symbol"];

const STRICT_STRATEGY_CONSTRUCTORS: &[&str] = &[
    // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error
    "Error",
    "EvalError",
    "RangeError",
    "ReferenceError",
    "SyntaxError",
    "TypeError",
    "URIError",

View on GitHub (pinned to e1e7af627c)

Solutions

  1. Apply the suggested replacement: `Array.isArray(x)`, `typeof x === 'string' | 'number' | 'boolean' | 'bigint' | 'symbol' | 'function'`, `Error.isError(e)` — most are auto-fixable
  2. For DOM constructors use duck typing: `el?.nodeType === 1` instead of `el instanceof HTMLElement`
  3. Configure the rule in .oxlintrc.json: strategy 'loose'|'strict', include/exclude name lists, useErrorIsError boolean

Example fix

// before
if (input instanceof String) {
  use(input);
}

// after
if (typeof input === 'string') {
  use(input);
}
Defensive patterns

Strategy: type-guard

Type guard

function isPrimitiveString(v: unknown): v is string {
  return typeof v === 'string';
}
function isErrorLike(v: unknown): v is Error {
  return typeof Error.isError === 'function'
    ? Error.isError(v)
    : Object.prototype.toString.call(v) === '[object Error]';
}

Prevention

When it happens

Trigger: `foo instanceof Array`, `x instanceof String`, `fn instanceof Function`, `err instanceof Error` (with useErrorIsError), and under strict strategy `v instanceof Map`, `r instanceof RegExp`, `d instanceof Date`, `buf instanceof Uint8Array`, etc. The right side must be a plain identifier resolving to the built-in.

Common situations: Hardening code that receives values from workers/iframes/vm sandboxes; replacing wrapper-object checks with primitive checks; teams adopting the strict strategy or extending coverage with include (e.g. HTMLElement, replaced by `el?.nodeType === 1`).

Related errors


AI-assisted analysis of oxc-project/oxc@e1e7af627c (2026-08-20). Data as JSON: /api/errors/207697f258ff490c. Report an issue: GitHub.