oxc-project/oxc · warning · OxcDiagnostic

'The `Object` type actually means "any non-nullish value"

Error message

'The `Object` type actually means "any non-nullish value"

What it means

Warning from typescript/ban-types via object() (crates/oxc_linter/src/rules/typescript/ban_types.rs:35). It fires when 'Object' is used as a type: Object means 'any non-nullish value' (including primitives), not 'any object'. The message text carries a stray leading apostrophe ("'The `Object` type actually means...") — a cosmetic string quirk in the rule, the diagnostic itself is correct.

Source

Thrown at crates/oxc_linter/src/rules/typescript/ban_types.rs:35

    .with_help(format!("Replace {banned_type:?} with the lowercase primitive type \"{suggested_type}\"."))
    .with_note(format!("{banned_type} is a wrapper object type, while {suggested_type} is the primitive type. Using the primitive type is more idiomatic and avoids confusion between the object wrapper and the primitive value."))
    .with_label(span)
}

fn type_literal(span: Span) -> OxcDiagnostic {
    OxcDiagnostic::warn("Prefer explicitly define the object shape")
        .with_help("This type means \"any non-nullish value\", which is slightly better than 'unknown', but it's still a broad type")
        .with_label(span)
}

fn function(span: Span) -> OxcDiagnostic {
    OxcDiagnostic::warn("Don't use `Function` as a type")
        .with_help("The `Function` type accepts any function-like value")
        .with_label(span)
}

fn object(span: Span) -> OxcDiagnostic {
    OxcDiagnostic::warn("'The `Object` type actually means \"any non-nullish value\"")
        .with_help("Replace `Object` with a more specific type. If you need a generic object, use `Record<string, unknown>` or define an interface/type with explicit properties. If you need any value, use `unknown` instead.")
        .with_note("The `Object` type is confusing because it doesn't mean 'any object' - it means 'any non-nullish value', which includes primitives. This makes code harder to understand and can lead to unexpected behavior.")
        .with_label(span)
}

#[derive(Debug, Default, Clone)]
pub struct BanTypes;

declare_oxc_lint!(
    /// ### What it does
    ///
    /// This rule bans specific types and can suggest alternatives. Note that it does not ban the corresponding runtime objects from being used.
    ///
    /// ::: warning
    /// This rule is deprecated and will be removed in a future release.
    ///
    /// Prefer these replacement rules:
    /// - `typescript/no-empty-object-type`

View on GitHub (pinned to e1e7af627c)

Solutions

  1. Use 'Record<string, unknown>' for dictionary-style values
  2. Declare an interface/type with the actual members you rely on
  3. Use 'unknown' when the value is genuinely opaque and narrow with type guards

Example fix

// before
function g(o: Object) {
  console.log(o);
}

// after
function g(o: Record<string, unknown>) {
  console.log(o);
}
Defensive patterns

Strategy: validation

Validate before calling

const OBJ = /:\s*Object\b/;
for (const line of source.split('\n')) {
  if (OBJ.test(line)) fail('Object used as a type; use Record<string, unknown> or an interface', line);
}

Type guard

function isRecord(v: unknown): v is Record<string, unknown> {
  return typeof v === 'object' && v !== null && !Array.isArray(v);
}

Prevention

When it happens

Trigger: A type reference to the global Object name: 'function g(o: Object) {}', 'const opts: Object = {}', 'Object' as a generic type argument — wherever the rule matches the banned global identifier in a type position.

Common situations: Java-influenced code where Object is the catch-all parameter type; loosely typed public APIs; Object-keys/Object-entries utilities annotated with Object instead of Record<string, unknown>.

Related errors


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