Flags Record<string, unknown> casts on vague parsed/payload variables like data, payload, and parsed.
- Family:
types - Severity:
strong - Scope:
file - Requires:
file.ast
The rule looks for as Record<string, unknown> casts assigned into generic object-bag variables such as:
parsedpayloadbodydataresultconfig
It gives extra detail when the cast comes directly from JSON.parse(...).
This pattern often shows up in generated or hurried glue code that turns unknown structured input into a generic property bag instead of validating it into a domain-shaped type.
To avoid obvious vendored noise, the rule skips very large bundled/generated files over 5000 logical lines.
const parsed = JSON.parse(raw) as Record<string, unknown>;
const payload = response as Record<string, unknown>;
const data = value as Record<string, unknown>;const parsed = JSON.parse(raw) as UserConfig;
const token = value as { token: string };
const metadata = input as Map<string, string>;Treat unknown input as unknown for longer, then validate or narrow it at the boundary.
Better options:
- parse into a real domain type with a schema or decoder
- keep the value as
unknownuntil you prove the fields you need - use a very local cast only when you immediately narrow and contain it
const input: unknown = JSON.parse(raw);
const parsed = UserConfigSchema.parse(input);Or, without a schema library:
const input: unknown = JSON.parse(raw);
if (!isUserConfig(input)) {
throw new Error("Invalid user config");
}The goal is to avoid turning uncertain external data into a roaming generic object bag that downstream code has to keep guessing about.
Each generic record cast adds 2 points.
The file total is capped at 8.
Small pinned rule benchmark (manifest):
- Signal rank: #7 of 9
- Signal score: 0.67 / 1.00
- Best separating metric: findings / file (0.75)
- Hit rate: 3/6 AI repos vs 0/5 mature OSS repos
- Full results: rule signal report