{"record":{"id":"9027c0b647501f18","repo":"oxc-project/oxc","slug":"always-prefer-const-x-t","errorCode":null,"errorMessage":"Always prefer `const x: T = { ... }`.","messagePattern":"Always prefer `const x: T = (.+?)`\\.","errorType":"validation","errorClass":"OxcDiagnostic","httpStatus":null,"severity":"warning","filePath":"crates/oxc_linter/src/rules/typescript/consistent_type_assertions.rs","lineNumber":39,"sourceCode":"fn use_angle_bracket_diagnostic(cast: &str, span: Span) -> OxcDiagnostic {\n    OxcDiagnostic::warn(format!(\"Use `<{cast}>` instead of `as {cast}`.\"))\n        .with_help(format!(\"Replace `as {cast}` with `<{cast}>`. For example, change `value as {cast}` to `<{cast}>value`.\"))\n        .with_label(span)\n}\n\nfn use_as_diagnostic(cast: &str, span: Span) -> OxcDiagnostic {\n    OxcDiagnostic::warn(format!(\"Use `as {cast}` instead of `<{cast}>`.\")).with_label(span)\n}\n\nfn never_diagnostic(span: Span) -> OxcDiagnostic {\n    OxcDiagnostic::warn(\"Do not use any type assertions.\")\n        .with_help(\"Remove the type assertion and use a type annotation instead. For example, change `const x = value as Type` to `const x: Type = value`. Alternatively, use the `satisfies` operator: `const x = value satisfies Type`.\")\n        .with_note(\"Type assertions bypass TypeScript's type checking and can hide type errors. Using type annotations or the `satisfies` operator provides better type safety while still allowing TypeScript to infer types where appropriate.\")\n        .with_label(span)\n}\n\nfn unexpected_object_type_assertion_diagnostic(span: Span) -> OxcDiagnostic {\n    OxcDiagnostic::warn(\"Always prefer `const x: T = { ... }`.\")\n        .with_help(\"Replace the object literal type assertion with a type annotation. For example, change `const x = { a: 1 } as Type` to `const x: Type = { a: 1 }`. Alternatively, use `const x = { a: 1 } satisfies Type` if you want TypeScript to infer the exact shape.\")\n        .with_note(\"Type assertions on object literals can hide errors where the object doesn't actually match the asserted type. Using type annotations or `satisfies` ensures TypeScript verifies that the object matches the expected type.\")\n        .with_label(span)\n}\n\nfn unexpected_array_type_assertion_diagnostic(span: Span) -> OxcDiagnostic {\n    OxcDiagnostic::warn(\"Always prefer `const x: T[] = [ ... ]`.\")\n        .with_help(\"Replace the array literal type assertion with a type annotation. For example, change `const x = [1, 2] as Type[]` to `const x: Type[] = [1, 2]`. Alternatively, use `const x = [1, 2] satisfies Type[]` if you want TypeScript to infer the exact array type.\")\n        .with_note(\"Type assertions on array literals can hide errors where the array doesn't actually match the asserted type. Using type annotations or `satisfies` ensures TypeScript verifies that the array matches the expected type.\")\n        .with_label(span)\n}\n\n#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Deserialize, JsonSchema)]\n#[serde(rename_all = \"kebab-case\")]\nenum AssertionStyle {\n    /// Enforce `as` syntax for type assertions.\n    ///\n    /// Examples of **incorrect** code with this option:","sourceCodeStart":21,"sourceCodeEnd":57,"githubUrl":"https://github.com/oxc-project/oxc/blob/e1e7af627c8843ab64044ed466b128fcc21a035b/crates/oxc_linter/src/rules/typescript/consistent_type_assertions.rs#L21-L57","documentation":"Warning from typescript/consistent-type-assertions via unexpected_object_type_assertion_diagnostic() (crates/oxc_linter/src/rules/typescript/consistent_type_assertions.rs:39). With objectLiteralTypeAssertions 'never' or 'allow-as-parameter', object literals must not be asserted; the rule demands 'const x: T = { ... }' (annotation) or 'satisfies', since asserting a literal skips exhaustiveness checking of its members.","triggerScenarios":"oxlint runs with objectLiteralTypeAssertions not set to 'allow' and the file contains 'const x = { a: 1 } as Type', 'foo({ b: 2 } as Options)', or '<Options>{ b: 2 }' — an assertion whose expression is an object literal (parenthesized parents count via outermost_paren_parent).","commonSituations":"Config objects initialized inline then cast to an options interface; default-parameter merges like '{ ...defaults, ...opts } as Config'; the cast hiding missing/renamed required properties after the target interface changes — exactly the class of bug the rule exists to catch.","solutions":["Annotate the variable: 'const x: Type = { a: 1 };'","Use 'const x = { a: 1 } satisfies Type;' to check compatibility while keeping the literal's inferred type","If the literal is genuinely partial (filling defaults), model it as 'const x: Partial<Type> = {...}' then merge, or type the factory function's return","Suppress rare intentional cases with an explained inline disable"],"exampleFix":"// before\nconst opts = { retries: 3 } as Options;\n\n// after\nconst opts: Options = { retries: 3 };","handlingStrategy":"validation","validationCode":"const OBJ_LITERAL_AS = /\\{[\\s\\S]*?\\}\\s*as\\s+\\w+|<\\w+>\\s*\\{/;\nif (OBJ_LITERAL_AS.test(source)) fail('object literal asserted; annotate or use satisfies');","typeGuard":"function isShape<T extends object>(v: unknown, keys: (keyof T)[]): v is T {\n  return typeof v === 'object' && v !== null && keys.every((k) => k in v);\n}","tryCatchPattern":null,"preventionTips":["Write 'const x: T = {...}' from the start","Use satisfies to check literals while keeping inference","Re-check literal sites when the target interface changes — the cast would have hidden the mismatch"],"tags":["typescript","oxlint","lint","type-assertion","object-literal","type-safety"],"backgroundTag":"type-assertion-style","analyzedSha":"e1e7af627c8843ab64044ed466b128fcc21a035b","analyzedAt":"2026-08-20T07:01:07.079Z","contentChangedAt":"2026-08-20T07:01:07.079Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}