Skip to content

Commit 3d23782

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 33628b4 commit 3d23782

File tree

4 files changed

+59
-26
lines changed

4 files changed

+59
-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
@@ -5442,7 +5442,8 @@ object.
54425442

54435443
However, `Object.create(null)` objects are not `instanceof Object`, however, so
54445444
in the case of such a plain object we lower-case to indicate possible support
5445-
for these objects. Also, nowadays, TypeScript also discourages use of `Object`
5445+
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.)
5446+
use of `Object`
54465447
as a lone type. However, one additional complexity is that TypeScript allows and
54475448
actually [currently requires](https://github.com/microsoft/TypeScript/issues/20555)
54485449
`Object` (with the initial upper-case) if used in the syntax
@@ -5451,8 +5452,14 @@ adhere to that which [JSDoc documents](https://jsdoc.app/tags-type.html).
54515452

54525453
So, for optimal compatibility with TypeScript (especially since TypeScript
54535454
tools can be used on plain JavaScript with JSDoc), we are now requiring this
5454-
TypeScript approach by default (if you set `object` type `preferredTypes` in
5455-
TypeScript mode, the defaults will not apply).
5455+
TypeScript approach by default in non-"typescript" mode (if you set
5456+
`object` type `preferredTypes` in TypeScript mode, the defaults will
5457+
not apply).
5458+
5459+
However, for "typescript" mode, a still better choice exists—using index signatures such as `{[key: string]: string}` or using a more precise
5460+
shorthand object syntax (e.g., `{a: string, b: number}`). This is superior
5461+
for TypeScript because the likes of `Object<string, number>` is not useable
5462+
in native TypeScript syntax, even if it is allowed within JSDoc.
54565463

54575464
Basically, for primitives, we want to define the type as a primitive, because
54585465
that's what we use in 99.9% of cases. For everything else, we use the type
@@ -6132,7 +6139,7 @@ function quux (foo) {
61326139

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

61376144
/**
61386145
*
@@ -6414,7 +6421,7 @@ function b () {}
64146421
function a () {}
64156422

64166423
/**
6417-
* @typedef {Object<string>} foo
6424+
* @typedef {{[key: string]: number}} foo
64186425
*/
64196426
function b () {}
64206427
// Settings: {"jsdoc":{"mode":"typescript"}}
@@ -6443,7 +6450,7 @@ function quux (foo) {
64436450
}
64446451

64456452
/**
6446-
* @param {Object<string>} foo
6453+
* @param {{[key: string]: number}} foo
64476454
*/
64486455
function quux (foo) {
64496456

src/rules/checkTypes.js

+33-6
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,11 @@ const adjustNames = (type, preferred, isGenericMatch, typeNodeName, node, parent
7373
}
7474
};
7575

76+
const getMessage = (upperCase) => {
77+
return 'Use object shorthand or index signatures instead of ' +
78+
'`' + (upperCase ? 'O' : 'o') + 'bject`, e.g., `{[key: string]: string}`';
79+
};
80+
7681
export default iterateJsdoc(({
7782
jsdocNode,
7883
sourceCode,
@@ -97,13 +102,35 @@ export default iterateJsdoc(({
97102
'Object.<>' in preferredTypesOriginal ||
98103
'object<>' in preferredTypesOriginal);
99104

100-
const preferredTypes = {
101-
...injectObjectPreferredTypes ? {
105+
const info = {
106+
message: getMessage(),
107+
replacement: false,
108+
};
109+
110+
const infoUC = {
111+
message: getMessage(true),
112+
replacement: false,
113+
};
114+
115+
const typeToInject = mode === 'typescript' ?
116+
{
117+
Object: 'object',
118+
'object.<>': info,
119+
'Object.<>': infoUC,
120+
'object<>': info,
121+
'Object<>': infoUC,
122+
} :
123+
{
102124
Object: 'object',
103125
'object.<>': 'Object<>',
104126
'Object.<>': 'Object<>',
105127
'object<>': 'Object<>',
106-
} : {},
128+
};
129+
130+
const preferredTypes = {
131+
...injectObjectPreferredTypes ?
132+
typeToInject :
133+
{},
107134
...preferredTypesOriginal,
108135
};
109136

@@ -364,7 +391,7 @@ export default iterateJsdoc(({
364391
for (const [
365392
badType,
366393
preferredType = '',
367-
message,
394+
msg,
368395
] of invalidTypes) {
369396
const tagValue = jsdocTag.name ? ` "${jsdocTag.name}"` : '';
370397
if (exemptTagContexts.some(({
@@ -378,13 +405,13 @@ export default iterateJsdoc(({
378405
}
379406

380407
report(
381-
message ||
408+
msg ||
382409
`Invalid JSDoc @${tagName}${tagValue} type "${badType}"` +
383410
(preferredType ? '; ' : '.') +
384411
(preferredType ? `prefer: ${JSON.stringify(preferredType)}.` : ''),
385412
preferredType ? fix : null,
386413
jsdocTag,
387-
message ? {
414+
msg ? {
388415
tagName,
389416
tagValue,
390417
} : 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)