oxc-project/oxc · warning · OxcDiagnostic

Do not use {banned_type:?} as a type. Use "{suggested_type}"

Error message

Do not use {banned_type:?} as a type. Use "{suggested_type}" instead

What it means

Warning from typescript/ban-types via type_diagnostic() (crates/oxc_linter/src/rules/typescript/ban_types.rs:14). It fires when a wrapper object type — String, Number, Boolean, or BigInt — is used in a type position, suggesting the lowercase primitive instead. Note the message uses Rust's {:?} debug formatting, so the type name prints quoted: Do not use "String" as a type.

Source

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

use cow_utils::CowUtils;
use oxc_ast::{AstKind, ast::TSTypeName};
use oxc_diagnostics::OxcDiagnostic;
use oxc_macros::declare_oxc_lint;
use oxc_span::Span;

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

fn type_diagnostic(banned_type: &str, suggested_type: &str, span: Span) -> OxcDiagnostic {
    OxcDiagnostic::warn(format!(
        "Do not use {banned_type:?} as a type. Use \"{suggested_type}\" instead"
    ))
    .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)
}

View on GitHub (pinned to e1e7af627c)

Solutions

  1. Change the annotation to the lowercase primitive: String→string, Number→number, Boolean→boolean, BigInt→bigint
  2. Run a project-wide rename for the affected annotations (these are pure type-level changes with no runtime effect)
  3. Only if you truly need the object wrapper (very rare), disable the rule for that line with an explained eslint-disable comment

Example fix

// before
function len(s: String): Number {
  return s.length;
}

// after
function len(s: string): number {
  return s.length;
}
Defensive patterns

Strategy: validation

Validate before calling

const WRAPPER = /:\s*(String|Number|Boolean|BigInt)\b/;
for (const line of source.split('\n')) {
  if (WRAPPER.test(line)) fail('wrapper object type in annotation', line);
}

Type guard

const PRIMITIVES = new Set(['string', 'number', 'boolean', 'bigint', 'symbol', 'null', 'undefined']);
function isPrimitiveTypeName(name: string): boolean {
  return PRIMITIVES.has(name);
}

Prevention

When it happens

Trigger: Type annotations or type references using a capitalized wrapper: 'let s: String = "x"', 'function f(x: Number): Boolean', 'const b: BigInt = 1n' — any position where the rule's run hits a TSTypeReference naming a banned wrapper.

Common situations: Developers coming from Java/C# where boxed types are idiomatic; code generated from templates or JSDoc that capitalized primitives; inconsistent typing across a large migrated codebase.

Related errors


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