{"record":{"id":"10cd0b821a7a6d25","repo":"oxc-project/oxc","slug":"prefer-explicitly-define-the-object-shape","errorCode":null,"errorMessage":"Prefer explicitly define the object shape","messagePattern":"Prefer explicitly define the object shape","errorType":"validation","errorClass":"OxcDiagnostic","httpStatus":null,"severity":"warning","filePath":"crates/oxc_linter/src/rules/typescript/ban_types.rs","lineNumber":23,"sourceCode":"use oxc_span::Span;\n\nuse crate::{\n    AstNode,\n    context::{ContextHost, LintContext},\n    rule::Rule,\n};\n\nfn type_diagnostic(banned_type: &str, suggested_type: &str, span: Span) -> OxcDiagnostic {\n    OxcDiagnostic::warn(format!(\n        \"Do not use {banned_type:?} as a type. Use \\\"{suggested_type}\\\" instead\"\n    ))\n    .with_help(format!(\"Replace {banned_type:?} with the lowercase primitive type \\\"{suggested_type}\\\".\"))\n    .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.\"))\n    .with_label(span)\n}\n\nfn type_literal(span: Span) -> OxcDiagnostic {\n    OxcDiagnostic::warn(\"Prefer explicitly define the object shape\")\n        .with_help(\"This type means \\\"any non-nullish value\\\", which is slightly better than 'unknown', but it's still a broad type\")\n        .with_label(span)\n}\n\nfn function(span: Span) -> OxcDiagnostic {\n    OxcDiagnostic::warn(\"Don't use `Function` as a type\")\n        .with_help(\"The `Function` type accepts any function-like value\")\n        .with_label(span)\n}\n\nfn object(span: Span) -> OxcDiagnostic {\n    OxcDiagnostic::warn(\"'The `Object` type actually means \\\"any non-nullish value\\\"\")\n        .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.\")\n        .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.\")\n        .with_label(span)\n}\n\n#[derive(Debug, Default, Clone)]","sourceCodeStart":5,"sourceCodeEnd":41,"githubUrl":"https://github.com/oxc-project/oxc/blob/e1e7af627c8843ab64044ed466b128fcc21a035b/crates/oxc_linter/src/rules/typescript/ban_types.rs#L5-L41","documentation":"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.","triggerScenarios":"Annotations like 'let x: {} = getValue()', function parameters typed '{}', or generic constraints using '{}' — any TSObjectTypeLiteral with zero members hit by the rule's visitor.","commonSituations":"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.","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"],"exampleFix":"// before\ndeclare function setProps(props: {}): void;\n\n// after\ndeclare function setProps(props: Record<string, unknown>): void;","handlingStrategy":"validation","validationCode":"const EMPTY = /:\\s*\\{\\s*\\}\\s*(;|,|\\)|=)/;\nif (EMPTY.test(source)) fail('empty object type {} used as a type');","typeGuard":"function isNonEmptyObjectType(t: unknown): t is Record<string, unknown> {\n  return typeof t === 'object' && t !== null && !Array.isArray(t);\n}","tryCatchPattern":null,"preventionTips":["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"],"tags":["typescript","oxlint","lint","ban-types","empty-object-type","type-safety"],"backgroundTag":"typescript-banned-types","analyzedSha":"e1e7af627c8843ab64044ed466b128fcc21a035b","analyzedAt":"2026-08-20T07:01:07.079Z","contentChangedAt":"2026-08-20T07:01:07.079Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}