From c5b3d2f2393f0bd4272b78c26c39dfee7ab496d3 Mon Sep 17 00:00:00 2001 From: Laura Trotta Date: Fri, 13 Jun 2025 12:42:31 +0200 Subject: [PATCH 1/3] hardcoded rule --- specification/eslint.config.js | 1 + validator/README.md | 9 +++--- validator/eslint-plugin-es-spec.js | 2 ++ validator/rules/no-native-types.js | 44 ++++++++++++++++++++++++++++++ 4 files changed, 52 insertions(+), 4 deletions(-) create mode 100644 validator/rules/no-native-types.js diff --git a/specification/eslint.config.js b/specification/eslint.config.js index 398377dbad..be1c5a2836 100644 --- a/specification/eslint.config.js +++ b/specification/eslint.config.js @@ -33,6 +33,7 @@ export default defineConfig({ rules: { 'es-spec-validator/single-key-dictionary-key-is-string': 'error', 'es-spec-validator/dictionary-key-is-string': 'error', + 'es-spec-validator/no-native-types': 'error', 'es-spec-validator/invalid-node-types': 'warn' } }) diff --git a/validator/README.md b/validator/README.md index d64b769259..5b57085972 100644 --- a/validator/README.md +++ b/validator/README.md @@ -5,11 +5,12 @@ It is configured [in the specification directory](../specification/eslint.config ## Rules -| Name | Description | -| - | - | +| Name | Description | +|---------------------------------------| - | | `single-key-dictionary-key-is-string` | `SingleKeyDictionary` keys must be strings. | -| `dictionary-key-is-string` | `Dictionary` keys must be strings. | -| `invalid-node-types` | The spec uses a subset of TypeScript, so some types, clauses and expressions are not allowed. | +| `dictionary-key-is-string` | `Dictionary` keys must be strings. | +| `no-native-types` | `Typescript native types not allowed, use aliases. | +| `invalid-node-types` | The spec uses a subset of TypeScript, so some types, clauses and expressions are not allowed. | ## Usage diff --git a/validator/eslint-plugin-es-spec.js b/validator/eslint-plugin-es-spec.js index e74b363579..aba3042515 100644 --- a/validator/eslint-plugin-es-spec.js +++ b/validator/eslint-plugin-es-spec.js @@ -18,12 +18,14 @@ */ import singleKeyDict from './rules/single-key-dictionary-key-is-string.js' import dict from './rules/dictionary-key-is-string.js' +import noNativeTypes from './rules/no-native-types.js' import invalidNodeTypes from './rules/invalid-node-types.js' export default { rules: { 'single-key-dictionary-key-is-string': singleKeyDict, 'dictionary-key-is-string': dict, + 'no-native-types': noNativeTypes, 'invalid-node-types': invalidNodeTypes, } } diff --git a/validator/rules/no-native-types.js b/validator/rules/no-native-types.js new file mode 100644 index 0000000000..55dc9de616 --- /dev/null +++ b/validator/rules/no-native-types.js @@ -0,0 +1,44 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +import { ESLintUtils } from '@typescript-eslint/utils'; + +const createRule = ESLintUtils.RuleCreator(name => `https://example.com/rule/${name}`) + +export default createRule({ + name: 'no-native-types', + create(context) { + return { + TSTypeReference(node) { + if (node.typeName.name === 'Record' || node.typeName.name === 'Map' ) { + context.report({ node, messageId: 'stringKey' }) + } + }, + } + }, + meta: { + docs: { + description: 'Typescript native types not allowed, use aliases', + }, + messages: { + stringKey: "Typescript native types not allowed, use aliases" + }, + type: 'suggestion', + }, + defaultOptions: [] +}) From 9bd9e16afe0e267aaf095a4abedd1e42c4810b62 Mon Sep 17 00:00:00 2001 From: Laura Trotta Date: Fri, 13 Jun 2025 18:55:33 +0200 Subject: [PATCH 2/3] a bit less hardcoded (still) --- validator/rules/no-native-types.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/validator/rules/no-native-types.js b/validator/rules/no-native-types.js index 55dc9de616..b21c2fa96a 100644 --- a/validator/rules/no-native-types.js +++ b/validator/rules/no-native-types.js @@ -20,12 +20,14 @@ 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']; + export default createRule({ name: 'no-native-types', create(context) { return { TSTypeReference(node) { - if (node.typeName.name === 'Record' || node.typeName.name === 'Map' ) { + if (TYPES_TO_AVOID.includes(node.typeName.name)) { context.report({ node, messageId: 'stringKey' }) } }, From e4ed6cb93e8349ea137bddb8719cc9c42ed0e22c Mon Sep 17 00:00:00 2001 From: Laura Trotta Date: Fri, 13 Jun 2025 19:03:28 +0200 Subject: [PATCH 3/3] test --- validator/test/no-native-types.test.js | 63 ++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 validator/test/no-native-types.test.js diff --git a/validator/test/no-native-types.test.js b/validator/test/no-native-types.test.js new file mode 100644 index 0000000000..ef30f764ca --- /dev/null +++ b/validator/test/no-native-types.test.js @@ -0,0 +1,63 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +import { RuleTester } from '@typescript-eslint/rule-tester' +import rule from '../rules/dictionary-key-is-string.js' + +const ruleTester = new RuleTester({ + languageOptions: { + parserOptions: { + projectService: { + allowDefaultProject: ['*.ts*'], + }, + tsconfigRootDir: import.meta.dirname, + }, + }, +}) + +ruleTester.run('no-native-types', rule, { + valid: [ + `type MyRecord = Record`, + `type MyPart = Partial`, + `type MyReq = Required`, + `type MyPick Pick`, + `type MyOmit = Omit`, + ], + invalid: [ + { + code: `type MyRecord = Record`, + errors: [{ messageId: 'stringKey' }] + }, + { + code: `type MyPart = Partial`, + errors: [{ messageId: 'stringKey' }] + }, + { + code: `type MyReq = Required`, + errors: [{ messageId: 'stringKey' }] + }, + { + code: `type MyPick Pick`, + errors: [{ messageId: 'stringKey' }] + }, + { + code: `type MyOmit = Omit`, + errors: [{ messageId: 'stringKey' }] + } + ], +})