Skip to content

Commit 65a3520

Browse files
committed
docs(linter): Improve diagnostic for consistent-type-definitions rule. (#15752)
Fix the grammar of the diagnostic message and improve the docs a bit. This removes the redundant help message, but that results in the fix message showing up, which can look a bit weird for multi-line fixes? Not sure if I should keep this as-is or add a static help message. Also adds an extra test case.
1 parent a4615e5 commit 65a3520

File tree

2 files changed

+121
-62
lines changed

2 files changed

+121
-62
lines changed

crates/oxc_linter/src/rules/typescript/consistent_type_definitions.rs

Lines changed: 21 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -17,23 +17,26 @@ use crate::{
1717
};
1818

1919
fn consistent_type_definitions_diagnostic(
20-
preferred_type_kind: &str,
21-
bad_type_kind: &str,
20+
config: ConsistentTypeDefinitionsConfig,
2221
span: Span,
2322
) -> OxcDiagnostic {
24-
OxcDiagnostic::warn(format!("Use an `{preferred_type_kind}` instead of a `{bad_type_kind}`"))
25-
.with_help(format!("Use an `{preferred_type_kind}` instead of a `{bad_type_kind}`"))
26-
.with_label(span)
23+
let message = match config {
24+
ConsistentTypeDefinitionsConfig::Interface => "Use `interface` instead of `type`.",
25+
ConsistentTypeDefinitionsConfig::Type => "Use `type` instead of `interface`.",
26+
};
27+
28+
OxcDiagnostic::warn(message).with_label(span)
2729
}
2830

2931
#[derive(Debug, Default, Clone, JsonSchema, Deserialize, Serialize)]
3032
#[serde(rename_all = "camelCase", default)]
3133
pub struct ConsistentTypeDefinitions {
32-
/// Configuration option to enforce either 'interface' or 'type' for object type definitions.
34+
/// Configuration option to enforce either `interface` or `type` for object type definitions.
3335
///
3436
/// Setting to `type` enforces the use of types for object type definitions.
3537
///
3638
/// Examples of **incorrect** code for this option:
39+
///
3740
/// ```typescript
3841
/// interface T {
3942
/// x: number;
@@ -58,11 +61,11 @@ enum ConsistentTypeDefinitionsConfig {
5861
declare_oxc_lint!(
5962
/// ### What it does
6063
///
61-
/// Enforce type definitions to consistently use either interface or type.
64+
/// Enforce type definitions to consistently use either `interface` or `type`.
6265
///
6366
/// ### Why is this bad?
6467
///
65-
/// TypeScript provides two common ways to define an object type: interface and type.
68+
/// TypeScript provides two common ways to define an object type: `interface` and `type`.
6669
/// The two are generally very similar, and can often be used interchangeably.
6770
/// Using the same type declaration style consistently helps with code readability.
6871
///
@@ -135,8 +138,7 @@ impl Rule for ConsistentTypeDefinitions {
135138

136139
ctx.diagnostic_with_fix(
137140
consistent_type_definitions_diagnostic(
138-
"interface",
139-
"type",
141+
ConsistentTypeDefinitionsConfig::Interface,
140142
Span::new(start, start + 4),
141143
),
142144
|fixer| {
@@ -175,8 +177,7 @@ impl Rule for ConsistentTypeDefinitions {
175177

176178
ctx.diagnostic_with_fix(
177179
consistent_type_definitions_diagnostic(
178-
"type",
179-
"interface",
180+
ConsistentTypeDefinitionsConfig::Type,
180181
Span::sized(decl.span.start, 9),
181182
),
182183
|fixer| {
@@ -221,8 +222,7 @@ impl Rule for ConsistentTypeDefinitions {
221222

222223
ctx.diagnostic_with_fix(
223224
consistent_type_definitions_diagnostic(
224-
"type",
225-
"interface",
225+
ConsistentTypeDefinitionsConfig::Type,
226226
Span::sized(start, 9),
227227
),
228228
|fixer| {
@@ -259,6 +259,7 @@ fn test() {
259259
),
260260
("type U = string;", Some(serde_json::json!(["interface"]))),
261261
("type V = { x: number } | { y: string };", Some(serde_json::json!(["interface"]))),
262+
("interface T { x: \"interface\" | \"type\"; }", Some(serde_json::json!(["interface"]))),
262263
(
263264
"
264265
type Record<T, U> = {
@@ -295,6 +296,7 @@ fn test() {
295296
("interface T { x: number; }", Some(serde_json::json!(["type"]))),
296297
("interface T{ x: number; }", Some(serde_json::json!(["type"]))),
297298
("interface T { x: number; }", Some(serde_json::json!(["type"]))),
299+
("type T = { x: \"interface\" | \"type\"; };", Some(serde_json::json!(["interface"]))),
298300
("interface A extends B, C { x: number; };", Some(serde_json::json!(["type"]))),
299301
("interface A extends B<T1>, C<T2> { x: number; };", Some(serde_json::json!(["type"]))),
300302
(
@@ -406,6 +408,11 @@ fn test() {
406408
}",
407409
Some(serde_json::json!(["interface"])),
408410
),
411+
(
412+
"type T = { x: \"interface\" | \"type\"; };",
413+
"interface T { x: \"interface\" | \"type\"; }",
414+
Some(serde_json::json!(["interface"])),
415+
),
409416
(
410417
"interface T { x: number; }",
411418
"type T = { x: number; }",
Lines changed: 100 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1,190 +1,242 @@
11
---
22
source: crates/oxc_linter/src/tester.rs
33
---
4-
typescript-eslint(consistent-type-definitions): Use an `interface` instead of a `type`
4+
typescript-eslint(consistent-type-definitions): Use `interface` instead of `type`.
55
╭─[consistent_type_definitions.tsx:1:1]
66
1type T = { x: number; };
77
· ────
88
╰────
9-
help: Use an `interface` instead of a `type`
9+
help: Replace `type T = { x: number; };` with `interface T { x: number; }`.
1010

11-
typescript-eslint(consistent-type-definitions): Use an `interface` instead of a `type`
11+
typescript-eslint(consistent-type-definitions): Use `interface` instead of `type`.
1212
╭─[consistent_type_definitions.tsx:1:1]
1313
1type T={ x: number; };
1414
· ────
1515
╰────
16-
help: Use an `interface` instead of a `type`
16+
help: Replace `type T={ x: number; };` with `interface T { x: number; }`.
1717

18-
typescript-eslint(consistent-type-definitions): Use an `interface` instead of a `type`
18+
typescript-eslint(consistent-type-definitions): Use `interface` instead of `type`.
1919
╭─[consistent_type_definitions.tsx:1:1]
2020
1type T= { x: number; };
2121
· ────
2222
╰────
23-
help: Use an `interface` instead of a `type`
23+
help: Replace `type T= { x: number; };` with `interface T { x: number; }`.
2424

25-
typescript-eslint(consistent-type-definitions): Use an `interface` instead of a `type`
25+
typescript-eslint(consistent-type-definitions): Use `interface` instead of `type`.
2626
╭─[consistent_type_definitions.tsx:2:11]
2727
1
2828
2export type W<T> = {
2929
· ────
3030
3 │ x: T;
3131
╰────
32-
help: Use an `interface` instead of a `type`
32+
help: Replace `type W<T> = {
33+
x: T;
34+
};` with `interface W<T> {
35+
x: T;
36+
}`.
3337

34-
⚠ typescript-eslint(consistent-type-definitions): Use an `type` instead of a `interface`
38+
⚠ typescript-eslint(consistent-type-definitions): Use `type` instead of `interface`.
3539
╭─[consistent_type_definitions.tsx:1:1]
3640
1 │ interface T { x: number; }
3741
· ─────────
3842
╰────
39-
help: Use an `type` instead of a `interface`
43+
help: Replace `interface T { x: number; }` with `type T = { x: number; }`.
4044

41-
⚠ typescript-eslint(consistent-type-definitions): Use an `type` instead of a `interface`
45+
typescript-eslint(consistent-type-definitions): Use `type` instead of `interface`.
4246
╭─[consistent_type_definitions.tsx:1:1]
4347
1 │ interface T{ x: number; }
4448
· ─────────
4549
╰────
46-
help: Use an `type` instead of a `interface`
50+
help: Replace `interface T{ x: number; }` with `type T = { x: number; }`.
4751

48-
⚠ typescript-eslint(consistent-type-definitions): Use an `type` instead of a `interface`
52+
typescript-eslint(consistent-type-definitions): Use `type` instead of `interface`.
4953
╭─[consistent_type_definitions.tsx:1:1]
5054
1 │ interface T { x: number; }
5155
· ─────────
5256
╰────
53-
help: Use an `type` instead of a `interface`
57+
help: Replace `interface T { x: number; }` with `type T = { x: number; }`.
5458

55-
⚠ typescript-eslint(consistent-type-definitions): Use an `type` instead of a `interface`
59+
typescript-eslint(consistent-type-definitions): Use `interface` instead of `type`.
60+
╭─[consistent_type_definitions.tsx:1:1]
61+
1 │ type T = { x: "interface" | "type"; };
62+
· ────
63+
╰────
64+
help: Replace `type T = { x: "interface" | "type"; };` with `interface T { x: "interface" | "type"; }`.
65+
66+
⚠ typescript-eslint(consistent-type-definitions): Use `type` instead of `interface`.
5667
╭─[consistent_type_definitions.tsx:1:1]
5768
1 │ interface A extends B, C { x: number; };
5869
· ─────────
5970
╰────
60-
help: Use an `type` instead of a `interface`
71+
help: Replace `interface A extends B, C { x: number; }` with `type A = { x: number; } & B & C`.
6172

62-
typescript-eslint(consistent-type-definitions): Use an `type` instead of a `interface`
73+
typescript-eslint(consistent-type-definitions): Use `type` instead of `interface`.
6374
╭─[consistent_type_definitions.tsx:1:1]
6475
1 │ interface A extends B<T1>, C<T2> { x: number; };
6576
· ─────────
6677
╰────
67-
help: Use an `type` instead of a `interface`
78+
help: Replace `interface A extends B<T1>, C<T2> { x: number; }` with `type A = { x: number; } & B<T1> & C<T2>`.
6879
69-
typescript-eslint(consistent-type-definitions): Use an `type` instead of a `interface`
80+
⚠ typescript-eslint(consistent-type-definitions): Use `type` instead of `interface`.
7081
╭─[consistent_type_definitions.tsx:2:11]
7182
1 │
7283
2 │ export interface W<T> {
7384
· ─────────
7485
3x: T;
7586
╰────
76-
help: Use an `type` instead of a `interface`
87+
help: Replace `interface W<T> {
88+
x: T;
89+
}` with `type W<T> = {
90+
x: T;
91+
}`.
7792
78-
typescript-eslint(consistent-type-definitions): Use an `type` instead of a `interface`
93+
⚠ typescript-eslint(consistent-type-definitions): Use `type` instead of `interface`.
7994
╭─[consistent_type_definitions.tsx:3:6]
8095
2 │ namespace JSX {
8196
3interface Array<T> {
8297
· ─────────
8398
4 │ foo(x: (x: number) => T): T[];
8499
╰────
85-
help: Use an `type` instead of a `interface`
100+
help: Replace `interface Array<T> {
101+
foo(x: (x: number) => T): T[];
102+
}` with `type Array<T> = {
103+
foo(x: (x: number) => T): T[];
104+
}`.
86105
87-
typescript-eslint(consistent-type-definitions): Use an `type` instead of a `interface`
106+
⚠ typescript-eslint(consistent-type-definitions): Use `type` instead of `interface`.
88107
╭─[consistent_type_definitions.tsx:3:6]
89108
2 │ global {
90109
3interface Array<T> {
91110
· ─────────
92111
4 │ foo(x: (x: number) => T): T[];
93112
╰────
94-
help: Use an `type` instead of a `interface`
113+
help: Replace `interface Array<T> {
114+
foo(x: (x: number) => T): T[];
115+
}` with `type Array<T> = {
116+
foo(x: (x: number) => T): T[];
117+
}`.
95118
96-
typescript-eslint(consistent-type-definitions): Use an `type` instead of a `interface`
119+
⚠ typescript-eslint(consistent-type-definitions): Use `type` instead of `interface`.
97120
╭─[consistent_type_definitions.tsx:3:6]
98121
2 │ declare global {
99122
3interface Array<T> {
100123
· ─────────
101124
4 │ foo(x: (x: number) => T): T[];
102125
╰────
103-
help: Use an `type` instead of a `interface`
126+
help: Replace `interface Array<T> {
127+
foo(x: (x: number) => T): T[];
128+
}` with `type Array<T> = {
129+
foo(x: (x: number) => T): T[];
130+
}`.
104131
105-
typescript-eslint(consistent-type-definitions): Use an `type` instead of a `interface`
132+
⚠ typescript-eslint(consistent-type-definitions): Use `type` instead of `interface`.
106133
╭─[consistent_type_definitions.tsx:4:8]
107134
3 │ namespace Foo {
108135
4interface Bar {}
109136
· ─────────
110137
5}
111138
╰────
112-
help: Use an `type` instead of a `interface`
139+
help: Replace `interface Bar {}` with `type Bar = {}`.
113140
114-
typescript-eslint(consistent-type-definitions): Use an `type` instead of a `interface`
141+
⚠ typescript-eslint(consistent-type-definitions): Use `type` instead of `interface`.
115142
╭─[consistent_type_definitions.tsx:2:19]
116143
1 │
117144
2 │ export default interface Test {
118145
· ─────────
119146
3bar(): string;
120147
╰────
121-
help: Use an `type` instead of a `interface`
148+
help: Replace `export default interface Test {
149+
bar(): string;
150+
foo(): number;
151+
}` with `type Test = {
152+
bar(): string;
153+
foo(): number;
154+
}
155+
export default Test`.
122156
123-
typescript-eslint(consistent-type-definitions): Use an `type` instead of a `interface`
157+
typescript-eslint(consistent-type-definitions): Use `type` instead of `interface`.
124158
╭─[consistent_type_definitions.tsx:2:19]
125159
1
126160
2export default interface Test {
127161
· ─────────
128162
3 │ bar(): string;
129163
╰────
130-
help: Use an `type` instead of a `interface`
164+
help: Replace `interface Test {
165+
bar(): string;
166+
foo(): number;
167+
}` with `type Test = {
168+
bar(): string;
169+
foo(): number;
170+
}`.
131171
132-
typescript-eslint(consistent-type-definitions): Use an `interface` instead of a `type`
172+
⚠ typescript-eslint(consistent-type-definitions): Use `interface` instead of `type`.
133173
╭─[consistent_type_definitions.tsx:2:19]
134174
1 │
135175
2 │ export declare type Test = {
136176
· ────
137177
3foo: string;
138178
╰────
139-
help: Use an `interface` instead of a `type`
179+
help: Replace `type Test = {
180+
foo: string;
181+
bar: string;
182+
};` with `interface Test {
183+
foo: string;
184+
bar: string;
185+
}`.
140186
141-
typescript-eslint(consistent-type-definitions): Use an `type` instead of a `interface`
187+
typescript-eslint(consistent-type-definitions): Use `type` instead of `interface`.
142188
╭─[consistent_type_definitions.tsx:2:19]
143189
1
144190
2export declare interface Test {
145191
· ─────────
146192
3 │ foo: string;
147193
╰────
148-
help: Use an `type` instead of a `interface`
194+
help: Replace `interface Test {
195+
foo: string;
196+
bar: string;
197+
}` with `type Test = {
198+
foo: string;
199+
bar: string;
200+
}`.
149201
150-
typescript-eslint(consistent-type-definitions): Use an `interface` instead of a `type`
202+
⚠ typescript-eslint(consistent-type-definitions): Use `interface` instead of `type`.
151203
╭─[consistent_type_definitions.tsx:1:10]
152204
1 │ declare…type S={}
153205
· ────
154206
╰────
155-
help: Use an `interface` instead of a `type`
207+
help: Replace `type S={}` with `interface S {}`.
156208
157-
typescript-eslint(consistent-type-definitions): Use an `type` instead of a `interface`
209+
⚠ typescript-eslint(consistent-type-definitions): Use `type` instead of `interface`.
158210
╭─[consistent_type_definitions.tsx:1:10]
159211
1 │ declare…interface S {}
160212
· ─────────
161213
╰────
162-
help: Use an `type` instead of a `interface`
214+
help: Replace `interface S {}` with `type S = {}`.
163215
164-
typescript-eslint(consistent-type-definitions): Use an `interface` instead of a `type`
216+
⚠ typescript-eslint(consistent-type-definitions): Use `interface` instead of `type`.
165217
╭─[consistent_type_definitions.tsx:1:17]
166218
1 │ export declare…type S={}
167219
· ────
168220
╰────
169-
help: Use an `interface` instead of a `type`
221+
help: Replace `type S={}` with `interface S {}`.
170222
171-
typescript-eslint(consistent-type-definitions): Use an `type` instead of a `interface`
223+
⚠ typescript-eslint(consistent-type-definitions): Use `type` instead of `interface`.
172224
╭─[consistent_type_definitions.tsx:1:17]
173225
1 │ export declare…interface S {}
174226
· ─────────
175227
╰────
176-
help: Use an `type` instead of a `interface`
228+
help: Replace `interface S {}` with `type S = {}`.
177229
178-
typescript-eslint(consistent-type-definitions): Use an `type` instead of a `interface`
230+
⚠ typescript-eslint(consistent-type-definitions): Use `type` instead of `interface`.
179231
╭─[consistent_type_definitions.tsx:1:25]
180232
1 │ declare /* interface */ interface T { x: number; };
181233
· ─────────
182234
╰────
183-
help: Use an `type` instead of a `interface`
235+
help: Replace `interface T { x: number; }` with `type T = { x: number; }`.
184236
185-
typescript-eslint(consistent-type-definitions): Use an `interface` instead of a `type`
237+
⚠ typescript-eslint(consistent-type-definitions): Use `interface` instead of `type`.
186238
╭─[consistent_type_definitions.tsx:1:20]
187239
1 │ declare /* type */ type T = { x: number; };
188240
· ────
189241
╰────
190-
help: Use an `interface` instead of a `type`
242+
help: Replace `type T = { x: number; };` with `interface T { x: number; }`.

0 commit comments

Comments
 (0)