Skip to content

Commit 33b0251

Browse files
committed
fix: for "typescript" mode, require object shorthand or index signatures; fixes gajus#1001
BREAKING CHANGE: For typescript mode, one must use object shorthand or index signatures, e.g., `{[key: string]: number}` or `{a: string, b: number}`
1 parent bd37392 commit 33b0251

File tree

4 files changed

+51
-26
lines changed

4 files changed

+51
-26
lines changed

.README/rules/check-types.md

+10-3
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,8 @@ object.
103103

104104
However, `Object.create(null)` objects are not `instanceof Object`, however, so
105105
in the case of such a plain object we lower-case to indicate possible support
106-
for these objects. Also, nowadays, TypeScript also discourages use of `Object`
106+
for these objects. Also, nowadays, TypeScript also [discourages](https://www.typescriptlang.org/docs/handbook/declaration-files/do-s-and-don-ts.html#:~:text=%E2%9D%8C%20Don't%20ever%20use,used%20appropriately%20in%20JavaScript%20code.)
107+
use of `Object`
107108
as a lone type. However, one additional complexity is that TypeScript allows and
108109
actually [currently requires](https://github.com/microsoft/TypeScript/issues/20555)
109110
`Object` (with the initial upper-case) if used in the syntax
@@ -112,8 +113,14 @@ adhere to that which [JSDoc documents](https://jsdoc.app/tags-type.html).
112113

113114
So, for optimal compatibility with TypeScript (especially since TypeScript
114115
tools can be used on plain JavaScript with JSDoc), we are now requiring this
115-
TypeScript approach by default (if you set `object` type `preferredTypes` in
116-
TypeScript mode, the defaults will not apply).
116+
TypeScript approach by default in non-"typescript" mode (if you set
117+
`object` type `preferredTypes` in TypeScript mode, the defaults will
118+
not apply).
119+
120+
However, for "typescript" mode, a still better choice exists—using index signatures such as `{[key: string]: string}` or using a more precise
121+
shorthand object syntax (e.g., `{a: string, b: number}`). This is superior
122+
for TypeScript because the likes of `Object<string, number>` is not useable
123+
in native TypeScript syntax, even if it is allowed within JSDoc.
117124

118125
Basically, for primitives, we want to define the type as a primitive, because
119126
that's what we use in 99.9% of cases. For everything else, we use the type

README.md

+13-6
Original file line numberDiff line numberDiff line change
@@ -5262,7 +5262,8 @@ object.
52625262

52635263
However, `Object.create(null)` objects are not `instanceof Object`, however, so
52645264
in the case of such a plain object we lower-case to indicate possible support
5265-
for these objects. Also, nowadays, TypeScript also discourages use of `Object`
5265+
for these objects. Also, nowadays, TypeScript also [discourages](https://www.typescriptlang.org/docs/handbook/declaration-files/do-s-and-don-ts.html#:~:text=%E2%9D%8C%20Don't%20ever%20use,used%20appropriately%20in%20JavaScript%20code.)
5266+
use of `Object`
52665267
as a lone type. However, one additional complexity is that TypeScript allows and
52675268
actually [currently requires](https://github.com/microsoft/TypeScript/issues/20555)
52685269
`Object` (with the initial upper-case) if used in the syntax
@@ -5271,8 +5272,14 @@ adhere to that which [JSDoc documents](https://jsdoc.app/tags-type.html).
52715272

52725273
So, for optimal compatibility with TypeScript (especially since TypeScript
52735274
tools can be used on plain JavaScript with JSDoc), we are now requiring this
5274-
TypeScript approach by default (if you set `object` type `preferredTypes` in
5275-
TypeScript mode, the defaults will not apply).
5275+
TypeScript approach by default in non-"typescript" mode (if you set
5276+
`object` type `preferredTypes` in TypeScript mode, the defaults will
5277+
not apply).
5278+
5279+
However, for "typescript" mode, a still better choice exists—using index signatures such as `{[key: string]: string}` or using a more precise
5280+
shorthand object syntax (e.g., `{a: string, b: number}`). This is superior
5281+
for TypeScript because the likes of `Object<string, number>` is not useable
5282+
in native TypeScript syntax, even if it is allowed within JSDoc.
52765283

52775284
Basically, for primitives, we want to define the type as a primitive, because
52785285
that's what we use in 99.9% of cases. For everything else, we use the type
@@ -5952,7 +5959,7 @@ function quux (foo) {
59525959

59535960
}
59545961
// Settings: {"jsdoc":{"mode":"typescript"}}
5955-
// Message: Invalid JSDoc @param "foo" type "object"; prefer: "Object<>".
5962+
// Message: Use object shorthand or index signatures instead of `object`, e.g., `{[key: string]: string}`
59565963

59575964
/**
59585965
*
@@ -6234,7 +6241,7 @@ function b () {}
62346241
function a () {}
62356242

62366243
/**
6237-
* @typedef {Object<string>} foo
6244+
* @typedef {{[key: string]: number}} foo
62386245
*/
62396246
function b () {}
62406247
// Settings: {"jsdoc":{"mode":"typescript"}}
@@ -6263,7 +6270,7 @@ function quux (foo) {
62636270
}
62646271

62656272
/**
6266-
* @param {Object<string>} foo
6273+
* @param {{[key: string]: number}} foo
62676274
*/
62686275
function quux (foo) {
62696276

src/rules/checkTypes.js

+25-6
Original file line numberDiff line numberDiff line change
@@ -97,13 +97,32 @@ export default iterateJsdoc(({
9797
'Object.<>' in preferredTypesOriginal ||
9898
'object<>' in preferredTypesOriginal);
9999

100-
const preferredTypes = {
101-
...injectObjectPreferredTypes ? {
100+
const message = 'Use object shorthand or index signatures instead of ' +
101+
'`object`, e.g., `{[key: string]: string}`';
102+
const info = {
103+
message,
104+
replacement: false,
105+
};
106+
107+
const typeToInject = mode === 'typescript' ?
108+
{
109+
Object: 'object',
110+
'object.<>': info,
111+
'Object.<>': info,
112+
'object<>': info,
113+
'Object<>': info,
114+
} :
115+
{
102116
Object: 'object',
103117
'object.<>': 'Object<>',
104118
'Object.<>': 'Object<>',
105119
'object<>': 'Object<>',
106-
} : {},
120+
};
121+
122+
const preferredTypes = {
123+
...injectObjectPreferredTypes ?
124+
typeToInject :
125+
{},
107126
...preferredTypesOriginal,
108127
};
109128

@@ -364,7 +383,7 @@ export default iterateJsdoc(({
364383
for (const [
365384
badType,
366385
preferredType = '',
367-
message,
386+
msg,
368387
] of invalidTypes) {
369388
const tagValue = jsdocTag.name ? ` "${jsdocTag.name}"` : '';
370389
if (exemptTagContexts.some(({
@@ -378,13 +397,13 @@ export default iterateJsdoc(({
378397
}
379398

380399
report(
381-
message ||
400+
msg ||
382401
`Invalid JSDoc @${tagName}${tagValue} type "${badType}"` +
383402
(preferredType ? '; ' : '.') +
384403
(preferredType ? `prefer: ${JSON.stringify(preferredType)}.` : ''),
385404
preferredType ? fix : null,
386405
jsdocTag,
387-
message ? {
406+
msg ? {
388407
tagName,
389408
tagValue,
390409
} : null,

test/rules/assertions/checkTypes.js

+3-11
Original file line numberDiff line numberDiff line change
@@ -2339,17 +2339,9 @@ export default {
23392339
errors: [
23402340
{
23412341
line: 3,
2342-
message: 'Invalid JSDoc @param "foo" type "object"; prefer: "Object<>".',
2342+
message: 'Use object shorthand or index signatures instead of `object`, e.g., `{[key: string]: string}`',
23432343
},
23442344
],
2345-
output: `
2346-
/**
2347-
* @param {Object<string>} foo
2348-
*/
2349-
function quux (foo) {
2350-
2351-
}
2352-
`,
23532345
settings: {
23542346
jsdoc: {
23552347
mode: 'typescript',
@@ -2944,7 +2936,7 @@ export default {
29442936
function a () {}
29452937
29462938
/**
2947-
* @typedef {Object<string>} foo
2939+
* @typedef {{[key: string]: number}} foo
29482940
*/
29492941
function b () {}
29502942
`,
@@ -3020,7 +3012,7 @@ export default {
30203012
{
30213013
code: `
30223014
/**
3023-
* @param {Object<string>} foo
3015+
* @param {{[key: string]: number}} foo
30243016
*/
30253017
function quux (foo) {
30263018

0 commit comments

Comments
 (0)