From f701f0aac813c5492048d329d736f530d2517a4b Mon Sep 17 00:00:00 2001 From: margaretjgu Date: Fri, 31 Oct 2025 15:25:46 -0400 Subject: [PATCH 1/3] remove native collection types --- validator/README.md | 2 +- validator/rules/no-native-types.js | 30 ++++++++++++--- validator/test/no-native-types.test.js | 53 ++++++++++++++++++-------- 3 files changed, 63 insertions(+), 22 deletions(-) diff --git a/validator/README.md b/validator/README.md index 5b57085972..5713ad4415 100644 --- a/validator/README.md +++ b/validator/README.md @@ -9,7 +9,7 @@ It is configured [in the specification directory](../specification/eslint.config |---------------------------------------| - | | `single-key-dictionary-key-is-string` | `SingleKeyDictionary` keys must be strings. | | `dictionary-key-is-string` | `Dictionary` keys must be strings. | -| `no-native-types` | `Typescript native types not allowed, use aliases. | +| `no-native-types` | TypeScript native utility types (`Record`, `Partial`, etc.) and collection types (`Map`, `Set`, etc.) are not allowed. Use spec-defined aliases like `Dictionary` instead. | | `invalid-node-types` | The spec uses a subset of TypeScript, so some types, clauses and expressions are not allowed. | ## Usage diff --git a/validator/rules/no-native-types.js b/validator/rules/no-native-types.js index b21c2fa96a..b52df99fe3 100644 --- a/validator/rules/no-native-types.js +++ b/validator/rules/no-native-types.js @@ -20,25 +20,45 @@ import { ESLintUtils } from '@typescript-eslint/utils'; const createRule = ESLintUtils.RuleCreator(name => `https://example.com/rule/${name}`) -const TYPES_TO_AVOID = ['Record', 'Partial', 'Required', 'Pick', 'Omit']; +const UTILITY_TYPES = ['Record', 'Partial', 'Required', 'Pick', 'Omit']; + +const COLLECTION_TYPES = ['Map', 'Set', 'WeakMap', 'WeakSet']; + +const TYPES_TO_AVOID = [...UTILITY_TYPES, ...COLLECTION_TYPES]; + +const TYPE_SUGGESTIONS = { + 'Record': 'Use Dictionary instead', + 'Map': 'Use Dictionary instead', + 'Set': 'Use an array type instead (e.g., string[])', + 'WeakMap': 'Use Dictionary instead', + 'WeakSet': 'Use an array type instead', +}; export default createRule({ name: 'no-native-types', create(context) { return { TSTypeReference(node) { - if (TYPES_TO_AVOID.includes(node.typeName.name)) { - context.report({ node, messageId: 'stringKey' }) + const typeName = node.typeName.name; + if (TYPES_TO_AVOID.includes(typeName)) { + context.report({ + node, + messageId: 'noNativeType', + data: { + type: typeName, + suggestion: TYPE_SUGGESTIONS[typeName] || 'Use spec-defined aliases instead' + } + }) } }, } }, meta: { docs: { - description: 'Typescript native types not allowed, use aliases', + description: 'TypeScript native utility and collection types not allowed, use spec-defined aliases', }, messages: { - stringKey: "Typescript native types not allowed, use aliases" + noNativeType: 'Native TypeScript type "{{type}}" is not allowed. {{suggestion}}.' }, type: 'suggestion', }, diff --git a/validator/test/no-native-types.test.js b/validator/test/no-native-types.test.js index ef30f764ca..6d6007d95e 100644 --- a/validator/test/no-native-types.test.js +++ b/validator/test/no-native-types.test.js @@ -17,7 +17,7 @@ * under the License. */ import { RuleTester } from '@typescript-eslint/rule-tester' -import rule from '../rules/dictionary-key-is-string.js' +import rule from '../rules/no-native-types.js' const ruleTester = new RuleTester({ languageOptions: { @@ -32,32 +32,53 @@ const ruleTester = new RuleTester({ ruleTester.run('no-native-types', rule, { valid: [ - `type MyRecord = Record`, - `type MyPart = Partial`, - `type MyReq = Required`, - `type MyPick Pick`, - `type MyOmit = Omit`, + `type MyDict = Dictionary`, + `type MyMapping = Dictionary`, + `type MyArray = string[]`, + `type MyList = Array`, + `type MyType = { field: string }`, + `class MyClass { prop: integer }`, ], invalid: [ { code: `type MyRecord = Record`, - errors: [{ messageId: 'stringKey' }] + errors: [{ messageId: 'noNativeType' }] }, { - code: `type MyPart = Partial`, - errors: [{ messageId: 'stringKey' }] + code: `type MyPart = Partial`, + errors: [{ messageId: 'noNativeType' }] }, { - code: `type MyReq = Required`, - errors: [{ messageId: 'stringKey' }] + code: `type MyReq = Required`, + errors: [{ messageId: 'noNativeType' }] }, { - code: `type MyPick Pick`, - errors: [{ messageId: 'stringKey' }] + code: `type MyPick = Pick`, + errors: [{ messageId: 'noNativeType' }] }, { - code: `type MyOmit = Omit`, - errors: [{ messageId: 'stringKey' }] - } + code: `type MyOmit = Omit`, + errors: [{ messageId: 'noNativeType' }] + }, + { + code: `type MyMap = Map`, + errors: [{ messageId: 'noNativeType' }] + }, + { + code: `type MySet = Set`, + errors: [{ messageId: 'noNativeType' }] + }, + { + code: `type MyWeakMap = WeakMap`, + errors: [{ messageId: 'noNativeType' }] + }, + { + code: `type MyWeakSet = WeakSet`, + errors: [{ messageId: 'noNativeType' }] + }, + { + code: `class MyClass { items: Map }`, + errors: [{ messageId: 'noNativeType' }] + }, ], }) From 1b0da8f791df580ca9d97e04126762d059452f76 Mon Sep 17 00:00:00 2001 From: margaretjgu Date: Fri, 7 Nov 2025 10:34:24 -0500 Subject: [PATCH 2/3] fix rule --- validator/rules/no-native-types.js | 15 +++++++-------- validator/test/no-native-types.test.js | 5 ++++- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/validator/rules/no-native-types.js b/validator/rules/no-native-types.js index b52df99fe3..b2c20bb501 100644 --- a/validator/rules/no-native-types.js +++ b/validator/rules/no-native-types.js @@ -20,18 +20,17 @@ import { ESLintUtils } from '@typescript-eslint/utils'; const createRule = ESLintUtils.RuleCreator(name => `https://example.com/rule/${name}`) -const UTILITY_TYPES = ['Record', 'Partial', 'Required', 'Pick', 'Omit']; - -const COLLECTION_TYPES = ['Map', 'Set', 'WeakMap', 'WeakSet']; - -const TYPES_TO_AVOID = [...UTILITY_TYPES, ...COLLECTION_TYPES]; - const TYPE_SUGGESTIONS = { 'Record': 'Use Dictionary instead', + 'Partial': 'Use spec-defined aliases instead', + 'Required': 'Use spec-defined aliases instead', + 'Pick': 'Use spec-defined aliases instead', + 'Omit': 'Use spec-defined aliases instead', 'Map': 'Use Dictionary instead', 'Set': 'Use an array type instead (e.g., string[])', 'WeakMap': 'Use Dictionary instead', 'WeakSet': 'Use an array type instead', + 'Array': 'Use array syntax instead (e.g., string[])', }; export default createRule({ @@ -40,13 +39,13 @@ export default createRule({ return { TSTypeReference(node) { const typeName = node.typeName.name; - if (TYPES_TO_AVOID.includes(typeName)) { + if (TYPE_SUGGESTIONS[typeName]) { context.report({ node, messageId: 'noNativeType', data: { type: typeName, - suggestion: TYPE_SUGGESTIONS[typeName] || 'Use spec-defined aliases instead' + suggestion: TYPE_SUGGESTIONS[typeName] } }) } diff --git a/validator/test/no-native-types.test.js b/validator/test/no-native-types.test.js index 6d6007d95e..029b2eafff 100644 --- a/validator/test/no-native-types.test.js +++ b/validator/test/no-native-types.test.js @@ -35,7 +35,6 @@ ruleTester.run('no-native-types', rule, { `type MyDict = Dictionary`, `type MyMapping = Dictionary`, `type MyArray = string[]`, - `type MyList = Array`, `type MyType = { field: string }`, `class MyClass { prop: integer }`, ], @@ -80,5 +79,9 @@ ruleTester.run('no-native-types', rule, { code: `class MyClass { items: Map }`, errors: [{ messageId: 'noNativeType' }] }, + { + code: `type MyList = Array`, + errors: [{ messageId: 'noNativeType' }] + }, ], }) From 293b1776a4cba724354b54f0227e470711c71f79 Mon Sep 17 00:00:00 2001 From: margaretjgu Date: Fri, 7 Nov 2025 11:14:05 -0500 Subject: [PATCH 3/3] remove array type --- validator/rules/no-native-types.js | 1 - validator/test/no-native-types.test.js | 5 ----- 2 files changed, 6 deletions(-) diff --git a/validator/rules/no-native-types.js b/validator/rules/no-native-types.js index b2c20bb501..f10b3f9091 100644 --- a/validator/rules/no-native-types.js +++ b/validator/rules/no-native-types.js @@ -30,7 +30,6 @@ const TYPE_SUGGESTIONS = { 'Set': 'Use an array type instead (e.g., string[])', 'WeakMap': 'Use Dictionary instead', 'WeakSet': 'Use an array type instead', - 'Array': 'Use array syntax instead (e.g., string[])', }; export default createRule({ diff --git a/validator/test/no-native-types.test.js b/validator/test/no-native-types.test.js index 029b2eafff..e585ab93be 100644 --- a/validator/test/no-native-types.test.js +++ b/validator/test/no-native-types.test.js @@ -34,7 +34,6 @@ ruleTester.run('no-native-types', rule, { valid: [ `type MyDict = Dictionary`, `type MyMapping = Dictionary`, - `type MyArray = string[]`, `type MyType = { field: string }`, `class MyClass { prop: integer }`, ], @@ -79,9 +78,5 @@ ruleTester.run('no-native-types', rule, { code: `class MyClass { items: Map }`, errors: [{ messageId: 'noNativeType' }] }, - { - code: `type MyList = Array`, - errors: [{ messageId: 'noNativeType' }] - }, ], })