Skip to content

Commit 5bf04ca

Browse files
authored
fix(ban-types): suggest Record<string, never> when encountering {} (#778)
1 parent f8d3dfa commit 5bf04ca

File tree

1 file changed

+15
-6
lines changed

1 file changed

+15
-6
lines changed

src/rules/ban_types.rs

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ enum BannedType {
2020
Function,
2121
CapitalObject,
2222
LowerObject,
23+
EmptyObjectLiteral,
2324
}
2425

2526
impl BannedType {
@@ -30,6 +31,7 @@ impl BannedType {
3031
Function => "This provides no type safety because it represents all functions and classes",
3132
CapitalObject => "This type may be different from what you expect it to be",
3233
LowerObject => "This type is tricky to use so should be avoided if possible",
34+
EmptyObjectLiteral => "`{}` doesn't mean an empty object, but means any types other than `null` and `undefined`",
3335
}
3436
}
3537

@@ -45,6 +47,9 @@ impl BannedType {
4547
r#"If you want a type meaning "any object", use `Record<string, unknown>` instead. Or if you want a type meaning "any value", you probably want `unknown` instead."#
4648
}
4749
LowerObject => "Use `Record<string, unknown>` instead",
50+
EmptyObjectLiteral => {
51+
r#"If you want a type that means "empty object", use `Record<string, never>` instead"#
52+
}
4853
}
4954
}
5055
}
@@ -61,6 +66,7 @@ impl TryFrom<&str> for BannedType {
6166
"Function" => Ok(Self::Function),
6267
"Object" => Ok(Self::CapitalObject),
6368
"object" => Ok(Self::LowerObject),
69+
"{}" => Ok(Self::EmptyObjectLiteral),
6470
_ => Err(()),
6571
}
6672
}
@@ -108,8 +114,10 @@ With `Function`, it is better to explicitly define the entire function
108114
signature rather than use the non-specific `Function` type which won't give you
109115
type safety with the function.
110116
111-
Finally, `Object` means "any non-nullish value" rather than "any object type".
112-
`Record<string, unknown>` is a good choice for a meaning of "any object type".
117+
Finally, `Object` and `{}` means "any non-nullish value" rather than "any object
118+
type". `Record<string, unknown>` is a good choice for a meaning of "any object
119+
type". On the other hand `object` type means "any object type", but using
120+
`Record<string, unknown>` is much more preferable in this case too.
113121
114122
### Invalid:
115123
```typescript
@@ -131,6 +139,7 @@ let c: number;
131139
let d: symbol;
132140
let e: () => number;
133141
let f: Record<string, unknown>;
142+
let g = Record<string, never>;
134143
```
135144
"#
136145
}
@@ -167,8 +176,8 @@ impl Handler for BanTypesHandler {
167176
ctx.add_diagnostic_with_hint(
168177
ts_type_lit.span(),
169178
CODE,
170-
BannedType::CapitalObject.as_message(),
171-
BannedType::CapitalObject.as_hint(),
179+
BannedType::EmptyObjectLiteral.as_message(),
180+
BannedType::EmptyObjectLiteral.as_hint(),
172181
);
173182
}
174183
}
@@ -256,8 +265,8 @@ mod tests {
256265
"let a: {};": [
257266
{
258267
col: 7,
259-
message: message("Object"),
260-
hint: hint("Object"),
268+
message: message("{}"),
269+
hint: hint("{}"),
261270
}
262271
],
263272
"let a: { b: String };": [

0 commit comments

Comments
 (0)