{"record":{"id":"8021b4ef981f1d0f","repo":"oxc-project/oxc","slug":"typeof-comparisons-should-be-to-string-literals","errorCode":null,"errorMessage":"`typeof` comparisons should be to string literals.","messagePattern":"`typeof` comparisons should be to string literals\\.","errorType":"validation","errorClass":"OxcDiagnostic","httpStatus":null,"severity":"error","filePath":"crates/oxc_linter/src/rules/eslint/valid_typeof.rs","lineNumber":18,"sourceCode":"use schemars::JsonSchema;\n\nuse oxc_ast::{AstKind, ast::Expression};\nuse oxc_diagnostics::OxcDiagnostic;\nuse oxc_macros::declare_oxc_lint;\nuse oxc_span::{GetSpan, Span, best_match};\nuse oxc_syntax::operator::UnaryOperator;\nuse serde::Deserialize;\n\nuse crate::{\n    AstNode,\n    context::LintContext,\n    rule::{DefaultRuleConfig, Rule},\n};\n\nfn not_string(help: Option<&'static str>, span: Span) -> OxcDiagnostic {\n    let mut d =\n        OxcDiagnostic::warn(\"`typeof` comparisons should be to string literals.\").with_label(span);\n    if let Some(x) = help {\n        d = d.with_help(x);\n    }\n    d\n}\n\nfn invalid_value(help: Option<String>, span: Span) -> OxcDiagnostic {\n    let mut d = OxcDiagnostic::warn(\"Invalid `typeof` comparison value.\").with_label(span);\n    if let Some(x) = help {\n        d = d.with_help(x);\n    }\n    d\n}\n\n#[derive(Debug, Clone, Default, JsonSchema, Deserialize)]\n#[serde(rename_all = \"camelCase\", default, deny_unknown_fields)]\npub struct ValidTypeof {\n    /// The `requireStringLiterals` option when set to `true`, allows the comparison of `typeof`","sourceCodeStart":1,"sourceCodeEnd":36,"githubUrl":"https://github.com/oxc-project/oxc/blob/e1e7af627c8843ab64044ed466b128fcc21a035b/crates/oxc_linter/src/rules/eslint/valid_typeof.rs#L1-L36","documentation":"oxlint's `valid-typeof` rule (eslint, correctness) requires `typeof` expressions to be compared only against string literals (or other typeof expressions). This message comes from `not_string` and fires when the other side of the comparison is not a string literal — nearly always a missing pair of quotes.","triggerScenarios":"`typeof foo === undefined` (comparing against the identifier), `typeof bar === 1`, or — with `requireStringLiterals: true` — comparisons against variables or any non-literal expression.","commonSituations":"The classic `typeof x === undefined` bug where the developer means `\"undefined\"`; comparisons against constants holding type names when requireStringLiterals is enabled; copy-pasted feature-detection guards.","solutions":["Quote the expected value: `typeof x === \"undefined\"`","If the comparison target must be dynamic, turn off `requireStringLiterals` or compare two typeof expressions","Run `npx tsc --noEmit` as well — TypeScript flags non-overlapping typeof comparisons"],"exampleFix":"// before — compares against the identifier undefined, not the string\nif (typeof callback === undefined) return;\n\n// after\nif (typeof callback === \"undefined\") return;","handlingStrategy":"validation","validationCode":"// .oxlintrc.json\n{ \"rules\": { \"valid-typeof\": \"error\" } }\n// dual gate: npx tsc --noEmit && npx oxlint --deny-warnings src/","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always quote typeof comparison targets; treat `typeof x === undefined` as a red flag in review","Enable the eslint correctness category so valid-typeof runs by default","Run tsc alongside oxlint — the compiler also catches non-overlapping typeof comparisons","Prefer direct `x === undefined` checks over typeof when the binding is known to exist"],"tags":["lint","oxlint","eslint","typeof","correctness","operators"],"backgroundTag":"invalid-typeof-comparison","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"}