oxc-project/oxc · warning · OxcDiagnostic
Prefer explicitly define the object shape
Error message
Prefer explicitly define the object shape
What it means
Warning from typescript/ban-types via type_literal() (crates/oxc_linter/src/rules/typescript/ban_types.rs:23). It fires when '{}' is used as a type: the empty object type actually means 'any non-nullish value' (accepts numbers, strings, functions...), which is broader than 'any object' and hides intent.
Source
Thrown at crates/oxc_linter/src/rules/typescript/ban_types.rs:23
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)
}
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)]View on GitHub (pinned to e1e7af627c)
Solutions
- Use 'Record<string, unknown>' when you mean a string-keyed dictionary
- Use 'object' when you mean any non-primitive value
- Declare an explicit interface/type with the real members, or use 'unknown' when nothing is known about the value
Example fix
// before
declare function setProps(props: {}): void;
// after
declare function setProps(props: Record<string, unknown>): void; Defensive patterns
Strategy: validation
Validate before calling
const EMPTY = /:\s*\{\s*\}\s*(;|,|\)|=)/;
if (EMPTY.test(source)) fail('empty object type {} used as a type'); Type guard
function isNonEmptyObjectType(t: unknown): t is Record<string, unknown> {
return typeof t === 'object' && t !== null && !Array.isArray(t);
} Prevention
- Default to 'Record<string, unknown>' or 'object' when you mean a loose object
- Reserve '{}' for nothing — grep for it during reviews
- Let the lint rule run on changed files in CI to catch new occurrences
When it happens
Trigger: Annotations like 'let x: {} = getValue()', function parameters typed '{}', or generic constraints using '{}' — any TSObjectTypeLiteral with zero members hit by the rule's visitor.
Common situations: Using {} as a quick 'some object' placeholder during prototyping; TypeScript codebases where '{}' slipped in as a default generic constraint; refactors where an interface was emptied to '{}' instead of deleted.
Related errors
- Don't use `Function` as a type
- 'The `Object` type actually means "any non-nullish value"
- encountered allocation error
- Do not use {banned_type:?} as a type. Use "{suggested_type}"
- Do not use any type assertions.
AI-assisted analysis of oxc-project/oxc@e1e7af627c (2026-08-20).
Data as JSON: /api/errors/10cd0b821a7a6d25.
Report an issue: GitHub.