From efe6eb44ab7eacf7aed9ab813efd3e4f818013d5 Mon Sep 17 00:00:00 2001 From: Josh Goldberg Date: Sat, 6 Jul 2024 11:28:36 -0400 Subject: [PATCH 1/9] feat(eslint-plugin): backport no-unsafe-function type, no-wrapper-object-types from v8 to v7 --- .../eslint-plugin/docs/rules/ban-types.mdx | 5 + .../docs/rules/no-unsafe-function-type.mdx | 63 +++++ .../docs/rules/no-wrapper-object-types.mdx | 67 +++++ packages/eslint-plugin/src/rules/index.ts | 4 + .../src/rules/no-unsafe-function-type.ts | 50 ++++ .../src/rules/no-wrapper-object-types.ts | 71 +++++ packages/eslint-plugin/src/util/index.ts | 1 + packages/eslint-plugin/src/util/scopeUtils.ts | 15 ++ .../no-unsafe-function-type.shot | 35 +++ .../no-wrapper-object-types.shot | 33 +++ .../rules/no-unsafe-function-type.test.ts | 83 ++++++ .../rules/no-wrapper-object-types.test.ts | 242 ++++++++++++++++++ 12 files changed, 669 insertions(+) create mode 100644 packages/eslint-plugin/docs/rules/no-unsafe-function-type.mdx create mode 100644 packages/eslint-plugin/docs/rules/no-wrapper-object-types.mdx create mode 100644 packages/eslint-plugin/src/rules/no-unsafe-function-type.ts create mode 100644 packages/eslint-plugin/src/rules/no-wrapper-object-types.ts create mode 100644 packages/eslint-plugin/src/util/scopeUtils.ts create mode 100644 packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-unsafe-function-type.shot create mode 100644 packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-wrapper-object-types.shot create mode 100644 packages/eslint-plugin/tests/rules/no-unsafe-function-type.test.ts create mode 100644 packages/eslint-plugin/tests/rules/no-wrapper-object-types.test.ts diff --git a/packages/eslint-plugin/docs/rules/ban-types.mdx b/packages/eslint-plugin/docs/rules/ban-types.mdx index da30f4959116..9ce4d3427c06 100644 --- a/packages/eslint-plugin/docs/rules/ban-types.mdx +++ b/packages/eslint-plugin/docs/rules/ban-types.mdx @@ -9,6 +9,11 @@ import TabItem from '@theme/TabItem'; > > See **https://typescript-eslint.io/rules/ban-types** for documentation. +:::danger Deprecated +**This rule is deprecated** and will be removed in typescript-eslint@v8. +See _**[Replacement of `ban-types`](/blog/announcing-typescript-eslint-v8-beta#replacement-of-ban-types)**_ for more details. +::: + Some built-in types have aliases, while some types are considered dangerous or harmful. It's often a good idea to ban certain types to help with consistency and safety. diff --git a/packages/eslint-plugin/docs/rules/no-unsafe-function-type.mdx b/packages/eslint-plugin/docs/rules/no-unsafe-function-type.mdx new file mode 100644 index 000000000000..39c07c853b21 --- /dev/null +++ b/packages/eslint-plugin/docs/rules/no-unsafe-function-type.mdx @@ -0,0 +1,63 @@ +--- +description: 'Disallow using the unsafe built-in Function type.' +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +> 🛑 This file is source code, not the primary documentation location! 🛑 +> +> See **https://typescript-eslint.io/rules/no-unsafe-function-type** for documentation. + +TypeScript's built-in `Function` type allows being called with any number of arguments and returns type `any`. +`Function` also allows classes or plain objects that happen to possess all properties of the `Function` class. +It's generally better to specify function parameters and return types with the function type syntax. + +"Catch-all" function types include: + +- `() => void`: a function that has no parameters and whose return is ignored +- `(...args: never) => unknown`: a "top type" for functions that can be assigned any function type, but can't be called + +Examples of code for this rule: + + + + +```ts +let noParametersOrReturn: Function; +noParametersOrReturn = () => {}; + +let stringToNumber: Function; +stringToNumber = (text: string) => text.length; + +let identity: Function; +identity = value => value; +``` + + + + +```ts +let noParametersOrReturn: () => void; +noParametersOrReturn = () => {}; + +let stringToNumber: (text: string) => number; +stringToNumber = text => text.length; + +let identity: (value: T) => T; +identity = value => value; +``` + + + + +## When Not To Use It + +If your project is still onboarding to TypeScript, it might be difficult to fully replace all unsafe `Function` types with more precise function types. +You might consider using [ESLint disable comments](https://eslint.org/docs/latest/use/configure/rules#using-configuration-comments-1) for those specific situations instead of completely disabling this rule. + +## Related To + +- typescript-eslint@v8's [`no-empty-object-type`](https://v8--typescript-eslint.netlify.app/rules/no-empty-object-type) +- typescript-eslint@v8's [`no-restricted-types`](https://v8--typescript-eslint.netlify.app/rules/no-restricted-types) +- typescript-eslint@v8's [`no-wrapper-object-types`](https://v8--typescript-eslint.netlify.app/rules/no-wrapper-object-types) diff --git a/packages/eslint-plugin/docs/rules/no-wrapper-object-types.mdx b/packages/eslint-plugin/docs/rules/no-wrapper-object-types.mdx new file mode 100644 index 000000000000..9622ec5cf04e --- /dev/null +++ b/packages/eslint-plugin/docs/rules/no-wrapper-object-types.mdx @@ -0,0 +1,67 @@ +--- +description: 'Disallow using confusing built-in primitive class wrappers.' +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +> 🛑 This file is source code, not the primary documentation location! 🛑 +> +> See **https://typescript-eslint.io/rules/no-wrapper-object-types** for documentation. + +The JavaScript language has a set of language types, but some of them correspond to two TypeScript types, which look similar: `boolean`/`Boolean`, `number`/`Number`, `string`/`String`, `bigint`/`BigInt`, `symbol`/`Symbol`, `object`/`Object`. +The difference is that the lowercase variants are compiler intrinsics and specify the actual _runtime types_ (that is, the return value when you use the `typeof` operator), while the uppercase variants are _structural types_ defined in the library that can be satisfied by any user-defined object with the right properties, not just the real primitives. +JavaScript also has a "wrapper" class object for each of those primitives, such as [`Boolean`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean) and [`Number`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number). +These wrapper objects are assignable to the uppercase types, but not to the lowercase types. + +Using the primitives like `0` instead of object wrappers like `new Number(0)` is generally considered a JavaScript best practice. +JavaScript programs typically work with the real number primitives, rather than objects that "look like" numbers. +Primitives are simpler to conceptualize and work with `==` and `===` equality checks -- which their object equivalents do notDeepEqual. +As a result, using the lowercase type names like `number` instead of the uppercase names like `Number` helps make your code behave more reliably. + +Examples of code for this rule: + + + + +```ts +let myBigInt: BigInt; +let myBoolean: Boolean; +let myNumber: Number; +let myString: String; +let mySymbol: Symbol; + +let myObject: Object = 'allowed by TypeScript'; +``` + + + + +```ts +let myBigint: bigint; +let myBoolean: boolean; +let myNumber: number; +let myString: string; +let mySymbol: symbol; + +let myObject: object = "Type 'string' is not assignable to type 'object'."; +``` + + + + +## When Not To Use It + +If your project is a rare one that intentionally deals with the class equivalents of primitives, it might not be worthwhile to use this rule. +You might consider using [ESLint disable comments](https://eslint.org/docs/latest/use/configure/rules#using-configuration-comments-1) for those specific situations instead of completely disabling this rule. + +## Further Reading + +- [MDN documentation on primitives](https://developer.mozilla.org/en-US/docs/Glossary/Primitive) +- [MDN documentation on `string` primitives and `String` objects](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String#string_primitives_and_string_objects) + +## Related To + +- typescript-eslint@v8's [`no-empty-object-type`](https://v8--typescript-eslint.netlify.app/rules/no-empty-object-type) +- typescript-eslint@v8's [`no-restricted-types`](https://v8--typescript-eslint.netlify.app/rules/no-restricted-types) +- typescript-eslint@v8's [`no-unsafe-function-type`](https://v8--typescript-eslint.netlify.app/rules/no-unsafe-function-type) diff --git a/packages/eslint-plugin/src/rules/index.ts b/packages/eslint-plugin/src/rules/index.ts index 12a90d2515d1..6fd9249ac78b 100644 --- a/packages/eslint-plugin/src/rules/index.ts +++ b/packages/eslint-plugin/src/rules/index.ts @@ -92,6 +92,7 @@ import noUnsafeAssignment from './no-unsafe-assignment'; import noUnsafeCall from './no-unsafe-call'; import noUnsafeDeclarationMerging from './no-unsafe-declaration-merging'; import noUnsafeEnumComparison from './no-unsafe-enum-comparison'; +import noUnsafeFunctionType from './no-unsafe-function-type'; import noUnsafeMemberAccess from './no-unsafe-member-access'; import noUnsafeReturn from './no-unsafe-return'; import noUnsafeUnaryMinus from './no-unsafe-unary-minus'; @@ -102,6 +103,7 @@ import noUselessConstructor from './no-useless-constructor'; import noUselessEmptyExport from './no-useless-empty-export'; import noUselessTemplateLiterals from './no-useless-template-literals'; import noVarRequires from './no-var-requires'; +import noWrapperObjectTypes from './no-wrapper-object-types'; import nonNullableTypeAssertionStyle from './non-nullable-type-assertion-style'; import objectCurlySpacing from './object-curly-spacing'; import onlyThrowError from './only-throw-error'; @@ -243,6 +245,7 @@ export default { 'no-unsafe-member-access': noUnsafeMemberAccess, 'no-unsafe-return': noUnsafeReturn, 'no-unsafe-unary-minus': noUnsafeUnaryMinus, + 'no-unsafe-function-type': noUnsafeFunctionType, 'no-unused-expressions': noUnusedExpressions, 'no-unused-vars': noUnusedVars, 'no-use-before-define': noUseBeforeDefine, @@ -250,6 +253,7 @@ export default { 'no-useless-empty-export': noUselessEmptyExport, 'no-useless-template-literals': noUselessTemplateLiterals, 'no-var-requires': noVarRequires, + 'no-wrapper-object-types': noWrapperObjectTypes, 'non-nullable-type-assertion-style': nonNullableTypeAssertionStyle, 'object-curly-spacing': objectCurlySpacing, 'only-throw-error': onlyThrowError, diff --git a/packages/eslint-plugin/src/rules/no-unsafe-function-type.ts b/packages/eslint-plugin/src/rules/no-unsafe-function-type.ts new file mode 100644 index 000000000000..624c038f8ff7 --- /dev/null +++ b/packages/eslint-plugin/src/rules/no-unsafe-function-type.ts @@ -0,0 +1,50 @@ +import type { TSESTree } from '@typescript-eslint/utils'; +import { AST_NODE_TYPES } from '@typescript-eslint/utils'; + +import { createRule, isReferenceToGlobalFunction } from '../util'; + +export default createRule({ + name: 'no-unsafe-function-type', + meta: { + type: 'problem', + docs: { + description: 'Disallow using the unsafe built-in Function type', + recommended: 'recommended', + }, + fixable: 'code', + messages: { + bannedFunctionType: [ + 'The `Function` type accepts any function-like value.', + 'Prefer explicitly defining any function parameters and return type.', + ].join('\n'), + }, + schema: [], + }, + defaultOptions: [], + create(context) { + function checkBannedTypes(node: TSESTree.Node): void { + if ( + node.type === AST_NODE_TYPES.Identifier && + node.name === 'Function' && + isReferenceToGlobalFunction('Function', node, context.sourceCode) + ) { + context.report({ + node, + messageId: 'bannedFunctionType', + }); + } + } + + return { + TSClassImplements(node): void { + checkBannedTypes(node.expression); + }, + TSInterfaceHeritage(node): void { + checkBannedTypes(node.expression); + }, + TSTypeReference(node): void { + checkBannedTypes(node.typeName); + }, + }; + }, +}); diff --git a/packages/eslint-plugin/src/rules/no-wrapper-object-types.ts b/packages/eslint-plugin/src/rules/no-wrapper-object-types.ts new file mode 100644 index 000000000000..f51b6c8564b5 --- /dev/null +++ b/packages/eslint-plugin/src/rules/no-wrapper-object-types.ts @@ -0,0 +1,71 @@ +import type { TSESLint, TSESTree } from '@typescript-eslint/utils'; +import { AST_NODE_TYPES } from '@typescript-eslint/utils'; + +import { createRule, isReferenceToGlobalFunction } from '../util'; + +const classNames = new Set([ + 'BigInt', + // eslint-disable-next-line @typescript-eslint/internal/prefer-ast-types-enum + 'Boolean', + 'Number', + 'Object', + // eslint-disable-next-line @typescript-eslint/internal/prefer-ast-types-enum + 'String', + 'Symbol', +]); + +export default createRule({ + name: 'no-wrapper-object-types', + meta: { + type: 'problem', + docs: { + description: 'Disallow using confusing built-in primitive class wrappers', + recommended: 'recommended', + }, + fixable: 'code', + messages: { + bannedClassType: + 'Prefer using the primitive `{{preferred}}` as a type name, rather than the upper-cased `{{typeName}}`.', + }, + schema: [], + }, + defaultOptions: [], + create(context) { + function checkBannedTypes( + node: TSESTree.EntityName | TSESTree.Expression, + includeFix: boolean, + ): void { + const typeName = node.type === AST_NODE_TYPES.Identifier && node.name; + if ( + !typeName || + !classNames.has(typeName) || + !isReferenceToGlobalFunction(typeName, node, context.sourceCode) + ) { + return; + } + + const preferred = typeName.toLowerCase(); + + context.report({ + data: { typeName, preferred }, + fix: includeFix + ? (fixer): TSESLint.RuleFix => fixer.replaceText(node, preferred) + : undefined, + messageId: 'bannedClassType', + node, + }); + } + + return { + TSClassImplements(node): void { + checkBannedTypes(node.expression, false); + }, + TSInterfaceHeritage(node): void { + checkBannedTypes(node.expression, false); + }, + TSTypeReference(node): void { + checkBannedTypes(node.typeName, true); + }, + }; + }, +}); diff --git a/packages/eslint-plugin/src/util/index.ts b/packages/eslint-plugin/src/util/index.ts index 29a254d4990d..317fe1af66e3 100644 --- a/packages/eslint-plugin/src/util/index.ts +++ b/packages/eslint-plugin/src/util/index.ts @@ -15,6 +15,7 @@ export * from './isNullLiteral'; export * from './isUndefinedIdentifier'; export * from './misc'; export * from './objectIterators'; +export * from './scopeUtils'; export * from './types'; export * from './isAssignee'; diff --git a/packages/eslint-plugin/src/util/scopeUtils.ts b/packages/eslint-plugin/src/util/scopeUtils.ts new file mode 100644 index 000000000000..b350a7412106 --- /dev/null +++ b/packages/eslint-plugin/src/util/scopeUtils.ts @@ -0,0 +1,15 @@ +import type { TSESTree } from '@typescript-eslint/utils'; +import type { SourceCode } from '@typescript-eslint/utils/ts-eslint'; + +export function isReferenceToGlobalFunction( + calleeName: string, + node: TSESTree.Node, + sourceCode: SourceCode, +): boolean { + const ref = sourceCode + .getScope(node) + .references.find(ref => ref.identifier.name === calleeName); + + // ensure it's the "global" version + return !ref?.resolved?.defs.length; +} diff --git a/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-unsafe-function-type.shot b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-unsafe-function-type.shot new file mode 100644 index 000000000000..c77f15d6feb3 --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-unsafe-function-type.shot @@ -0,0 +1,35 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Validating rule docs no-unsafe-function-type.mdx code examples ESLint output 1`] = ` +"Incorrect + +let noParametersOrReturn: Function; + ~~~~~~~~ The \`Function\` type accepts any function-like value. + Prefer explicitly defining any function parameters and return type. +noParametersOrReturn = () => {}; + +let stringToNumber: Function; + ~~~~~~~~ The \`Function\` type accepts any function-like value. + Prefer explicitly defining any function parameters and return type. +stringToNumber = (text: string) => text.length; + +let identity: Function; + ~~~~~~~~ The \`Function\` type accepts any function-like value. + Prefer explicitly defining any function parameters and return type. +identity = value => value; +" +`; + +exports[`Validating rule docs no-unsafe-function-type.mdx code examples ESLint output 2`] = ` +"Correct + +let noParametersOrReturn: () => void; +noParametersOrReturn = () => {}; + +let stringToNumber: (text: string) => number; +stringToNumber = text => text.length; + +let identity: (value: T) => T; +identity = value => value; +" +`; diff --git a/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-wrapper-object-types.shot b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-wrapper-object-types.shot new file mode 100644 index 000000000000..4303b79a77a7 --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-wrapper-object-types.shot @@ -0,0 +1,33 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Validating rule docs no-wrapper-object-types.mdx code examples ESLint output 1`] = ` +"Incorrect + +let myBigInt: BigInt; + ~~~~~~ Prefer using the primitive \`bigint\` as a type name, rather than the upper-cased \`BigInt\`. +let myBoolean: Boolean; + ~~~~~~~ Prefer using the primitive \`boolean\` as a type name, rather than the upper-cased \`Boolean\`. +let myNumber: Number; + ~~~~~~ Prefer using the primitive \`number\` as a type name, rather than the upper-cased \`Number\`. +let myString: String; + ~~~~~~ Prefer using the primitive \`string\` as a type name, rather than the upper-cased \`String\`. +let mySymbol: Symbol; + ~~~~~~ Prefer using the primitive \`symbol\` as a type name, rather than the upper-cased \`Symbol\`. + +let myObject: Object = 'allowed by TypeScript'; + ~~~~~~ Prefer using the primitive \`object\` as a type name, rather than the upper-cased \`Object\`. +" +`; + +exports[`Validating rule docs no-wrapper-object-types.mdx code examples ESLint output 2`] = ` +"Correct + +let myBigint: bigint; +let myBoolean: boolean; +let myNumber: number; +let myString: string; +let mySymbol: symbol; + +let myObject: object = "Type 'string' is not assignable to type 'object'."; +" +`; diff --git a/packages/eslint-plugin/tests/rules/no-unsafe-function-type.test.ts b/packages/eslint-plugin/tests/rules/no-unsafe-function-type.test.ts new file mode 100644 index 000000000000..88e2d932a07b --- /dev/null +++ b/packages/eslint-plugin/tests/rules/no-unsafe-function-type.test.ts @@ -0,0 +1,83 @@ +import { RuleTester } from '@typescript-eslint/rule-tester'; + +import rule from '../../src/rules/no-unsafe-function-type'; + +const ruleTester = new RuleTester({ + parser: '@typescript-eslint/parser', +}); + +ruleTester.run('no-unsafe-function-type', rule, { + valid: [ + 'let value: () => void;', + 'let value: (t: T) => T;', + ` + type Function = () => void; + let value: Function; + `, + ], + invalid: [ + { + code: 'let value: Function;', + output: null, + errors: [ + { + messageId: 'bannedFunctionType', + line: 1, + column: 12, + }, + ], + }, + { + code: 'let value: Function[];', + output: null, + errors: [ + { + messageId: 'bannedFunctionType', + line: 1, + column: 12, + }, + ], + }, + { + code: 'let value: Function | number;', + output: null, + errors: [ + { + messageId: 'bannedFunctionType', + line: 1, + column: 12, + }, + ], + }, + { + code: ` + class Weird implements Function { + // ... + } + `, + output: null, + errors: [ + { + messageId: 'bannedFunctionType', + line: 2, + column: 32, + }, + ], + }, + { + code: ` + interface Weird extends Function { + // ... + } + `, + output: null, + errors: [ + { + messageId: 'bannedFunctionType', + line: 2, + column: 33, + }, + ], + }, + ], +}); diff --git a/packages/eslint-plugin/tests/rules/no-wrapper-object-types.test.ts b/packages/eslint-plugin/tests/rules/no-wrapper-object-types.test.ts new file mode 100644 index 000000000000..73613259cc22 --- /dev/null +++ b/packages/eslint-plugin/tests/rules/no-wrapper-object-types.test.ts @@ -0,0 +1,242 @@ +/* eslint-disable @typescript-eslint/internal/prefer-ast-types-enum */ +import { RuleTester } from '@typescript-eslint/rule-tester'; + +import rule from '../../src/rules/no-wrapper-object-types'; + +const ruleTester = new RuleTester({ + parser: '@typescript-eslint/parser', +}); + +ruleTester.run('no-wrapper-object-types', rule, { + valid: [ + 'let value: NumberLike;', + 'let value: Other;', + 'let value: bigint;', + 'let value: boolean;', + 'let value: never;', + 'let value: null;', + 'let value: number;', + 'let value: symbol;', + 'let value: undefined;', + 'let value: unknown;', + 'let value: void;', + 'let value: () => void;', + 'let value: () => () => void;', + 'let Bigint;', + 'let Boolean;', + 'let Never;', + 'let Null;', + 'let Number;', + 'let Symbol;', + 'let Undefined;', + 'let Unknown;', + 'let Void;', + 'interface Bigint {}', + 'interface Boolean {}', + 'interface Never {}', + 'interface Null {}', + 'interface Number {}', + 'interface Symbol {}', + 'interface Undefined {}', + 'interface Unknown {}', + 'interface Void {}', + 'type Bigint = {};', + 'type Boolean = {};', + 'type Never = {};', + 'type Null = {};', + 'type Number = {};', + 'type Symbol = {};', + 'type Undefined = {};', + 'type Unknown = {};', + 'type Void = {};', + 'class MyClass extends Number {}', + ` + type Number = 0 | 1; + let value: Number; + `, + ` + type Bigint = 0 | 1; + let value: Bigint; + `, + ` + type T = Symbol; + type U = UU extends T ? Function : never; + `, + ], + invalid: [ + { + code: 'let value: BigInt;', + output: 'let value: bigint;', + errors: [ + { + data: { typeName: 'BigInt', preferred: 'bigint' }, + messageId: 'bannedClassType', + line: 1, + column: 12, + }, + ], + }, + { + code: 'let value: Boolean;', + output: 'let value: boolean;', + errors: [ + { + data: { typeName: 'Boolean', preferred: 'boolean' }, + messageId: 'bannedClassType', + line: 1, + column: 12, + }, + ], + }, + { + code: 'let value: Number;', + output: 'let value: number;', + errors: [ + { + data: { typeName: 'Number', preferred: 'number' }, + messageId: 'bannedClassType', + line: 1, + column: 12, + }, + ], + }, + { + code: 'let value: Object;', + output: 'let value: object;', + errors: [ + { + data: { typeName: 'Object', preferred: 'object' }, + messageId: 'bannedClassType', + line: 1, + column: 12, + }, + ], + }, + { + code: 'let value: String;', + output: 'let value: string;', + errors: [ + { + data: { typeName: 'String', preferred: 'string' }, + messageId: 'bannedClassType', + line: 1, + column: 12, + }, + ], + }, + { + code: 'let value: Symbol;', + output: 'let value: symbol;', + errors: [ + { + data: { typeName: 'Symbol', preferred: 'symbol' }, + messageId: 'bannedClassType', + line: 1, + column: 12, + }, + ], + }, + { + code: 'let value: Number | Symbol;', + output: 'let value: number | symbol;', + errors: [ + { + data: { typeName: 'Number', preferred: 'number' }, + messageId: 'bannedClassType', + line: 1, + column: 12, + }, + { + data: { typeName: 'Symbol', preferred: 'symbol' }, + messageId: 'bannedClassType', + line: 1, + column: 21, + }, + ], + }, + { + code: 'let value: { property: Number };', + output: 'let value: { property: number };', + errors: [ + { + messageId: 'bannedClassType', + line: 1, + column: 24, + }, + ], + }, + { + code: '0 as Number;', + output: '0 as number;', + errors: [ + { + messageId: 'bannedClassType', + line: 1, + column: 6, + }, + ], + }, + { + code: 'type MyType = Number;', + output: 'type MyType = number;', + errors: [ + { + messageId: 'bannedClassType', + line: 1, + column: 15, + }, + ], + }, + { + code: 'type MyType = [Number];', + output: 'type MyType = [number];', + errors: [ + { + messageId: 'bannedClassType', + line: 1, + column: 16, + }, + ], + }, + { + code: 'class MyClass implements Number {}', + output: null, + errors: [ + { + messageId: 'bannedClassType', + line: 1, + column: 26, + }, + ], + }, + { + code: 'interface MyInterface extends Number {}', + output: null, + errors: [ + { + messageId: 'bannedClassType', + line: 1, + column: 31, + }, + ], + }, + { + code: 'type MyType = Number & String;', + output: 'type MyType = number & string;', + errors: [ + { + data: { preferred: 'number', typeName: 'Number' }, + messageId: 'bannedClassType', + line: 1, + column: 15, + }, + { + data: { preferred: 'string', typeName: 'String' }, + messageId: 'bannedClassType', + line: 1, + column: 24, + }, + ], + }, + ], +}); From 5ec359bb62fecdbb8d46ddcff623ffda74905984 Mon Sep 17 00:00:00 2001 From: Josh Goldberg Date: Mon, 8 Jul 2024 11:52:28 -0400 Subject: [PATCH 2/9] fix: lint --- packages/eslint-plugin/src/rules/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/eslint-plugin/src/rules/index.ts b/packages/eslint-plugin/src/rules/index.ts index 6fd9249ac78b..8288db9be6b6 100644 --- a/packages/eslint-plugin/src/rules/index.ts +++ b/packages/eslint-plugin/src/rules/index.ts @@ -242,10 +242,10 @@ export default { 'no-unsafe-call': noUnsafeCall, 'no-unsafe-declaration-merging': noUnsafeDeclarationMerging, 'no-unsafe-enum-comparison': noUnsafeEnumComparison, + 'no-unsafe-function-type': noUnsafeFunctionType, 'no-unsafe-member-access': noUnsafeMemberAccess, 'no-unsafe-return': noUnsafeReturn, 'no-unsafe-unary-minus': noUnsafeUnaryMinus, - 'no-unsafe-function-type': noUnsafeFunctionType, 'no-unused-expressions': noUnusedExpressions, 'no-unused-vars': noUnusedVars, 'no-use-before-define': noUseBeforeDefine, From e94c264be09e1e6e5414fda267d0895227fae287 Mon Sep 17 00:00:00 2001 From: Josh Goldberg Date: Sat, 13 Jul 2024 12:26:08 -0400 Subject: [PATCH 3/9] Brought in the rewording --- .../docs/rules/no-wrapper-object-types.mdx | 26 ++++++++++++------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/packages/eslint-plugin/docs/rules/no-wrapper-object-types.mdx b/packages/eslint-plugin/docs/rules/no-wrapper-object-types.mdx index 9622ec5cf04e..215dc0f7276f 100644 --- a/packages/eslint-plugin/docs/rules/no-wrapper-object-types.mdx +++ b/packages/eslint-plugin/docs/rules/no-wrapper-object-types.mdx @@ -9,15 +9,23 @@ import TabItem from '@theme/TabItem'; > > See **https://typescript-eslint.io/rules/no-wrapper-object-types** for documentation. -The JavaScript language has a set of language types, but some of them correspond to two TypeScript types, which look similar: `boolean`/`Boolean`, `number`/`Number`, `string`/`String`, `bigint`/`BigInt`, `symbol`/`Symbol`, `object`/`Object`. -The difference is that the lowercase variants are compiler intrinsics and specify the actual _runtime types_ (that is, the return value when you use the `typeof` operator), while the uppercase variants are _structural types_ defined in the library that can be satisfied by any user-defined object with the right properties, not just the real primitives. -JavaScript also has a "wrapper" class object for each of those primitives, such as [`Boolean`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean) and [`Number`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number). -These wrapper objects are assignable to the uppercase types, but not to the lowercase types. - -Using the primitives like `0` instead of object wrappers like `new Number(0)` is generally considered a JavaScript best practice. -JavaScript programs typically work with the real number primitives, rather than objects that "look like" numbers. -Primitives are simpler to conceptualize and work with `==` and `===` equality checks -- which their object equivalents do notDeepEqual. -As a result, using the lowercase type names like `number` instead of the uppercase names like `Number` helps make your code behave more reliably. +TypeScript defines several confusing pairs of types that look very similar to each other, but actually mean different things: `boolean`/`Boolean`, `number`/`Number`, `string`/`String`, `bigint`/`BigInt`, `symbol`/`Symbol`, `object`/`Object`. +In general, only the lowercase variant is appropriate to use. +Therefore, this rule enforces that you only use the lowercase variant. + +JavaScript has [8 data types](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures) at runtime, and these are described in TypeScript by the lowercase types `undefined`, `null`, `boolean`, `number`, `string`, `bigint`, `symbol`, and `object`. + +As for the uppercase types, these are _structural types_ which describe JavaScript "wrapper" objects for each of the data types, such as [`Boolean`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean) and [`Number`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number). +Additionally, due to the quirks of structural typing, the corresponding primitives are _also_ assignable to these uppercase types, since they have the same "shape". + +It is a universal best practice to work directly with the built-in primitives, like `0`, rather than objects that "look like" the corresponding primitive, like `new Number(0)`. + +- Primitives have the expected value semantics with `==` and `===` equality checks, whereas their object counterparts are compared by reference. + That is to say, `"str" === "str"` but `new String("str") !== new String("str")`. +- Primitives have well-known behavior around truthiness/falsiness which is common to rely on, whereas all objects are truthy, regardless of the wrapped value (e.g. `new Boolean(false)` is truthy). +- TypeScript only allows arithmetic operations (e.g. `x - y`) to be performed on numeric primitives, not objects. + +As a result, using the lowercase type names like `number` in TypeScript types instead of the uppercase names like `Number` is a better practice that describes code more accurately. Examples of code for this rule: From 6b8d0bc2756a3ac829c64be9ec34ee9f657585e8 Mon Sep 17 00:00:00 2001 From: Josh Goldberg Date: Sat, 13 Jul 2024 12:26:49 -0400 Subject: [PATCH 4/9] Remove v8 label in relations --- .../eslint-plugin/docs/rules/no-wrapper-object-types.mdx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/eslint-plugin/docs/rules/no-wrapper-object-types.mdx b/packages/eslint-plugin/docs/rules/no-wrapper-object-types.mdx index 215dc0f7276f..355d628ea8cb 100644 --- a/packages/eslint-plugin/docs/rules/no-wrapper-object-types.mdx +++ b/packages/eslint-plugin/docs/rules/no-wrapper-object-types.mdx @@ -70,6 +70,6 @@ You might consider using [ESLint disable comments](https://eslint.org/docs/lates ## Related To -- typescript-eslint@v8's [`no-empty-object-type`](https://v8--typescript-eslint.netlify.app/rules/no-empty-object-type) -- typescript-eslint@v8's [`no-restricted-types`](https://v8--typescript-eslint.netlify.app/rules/no-restricted-types) -- typescript-eslint@v8's [`no-unsafe-function-type`](https://v8--typescript-eslint.netlify.app/rules/no-unsafe-function-type) +- [`no-empty-object-type`](https://v8--typescript-eslint.netlify.app/rules/no-empty-object-type) +- [`no-restricted-types`](https://v8--typescript-eslint.netlify.app/rules/no-restricted-types) +- [`no-unsafe-function-type`](https://v8--typescript-eslint.netlify.app/rules/no-unsafe-function-type) From 711319e384be2be4ff598e73a105f0a64dac494c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Josh=20Goldberg=20=E2=9C=A8?= Date: Sat, 13 Jul 2024 14:11:37 -0400 Subject: [PATCH 5/9] Apply suggestions from code review Co-authored-by: Kirk Waiblinger --- packages/eslint-plugin/docs/rules/no-unsafe-function-type.mdx | 2 +- packages/eslint-plugin/docs/rules/no-wrapper-object-types.mdx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/eslint-plugin/docs/rules/no-unsafe-function-type.mdx b/packages/eslint-plugin/docs/rules/no-unsafe-function-type.mdx index 39c07c853b21..2c79d624c78d 100644 --- a/packages/eslint-plugin/docs/rules/no-unsafe-function-type.mdx +++ b/packages/eslint-plugin/docs/rules/no-unsafe-function-type.mdx @@ -58,6 +58,6 @@ You might consider using [ESLint disable comments](https://eslint.org/docs/lates ## Related To -- typescript-eslint@v8's [`no-empty-object-type`](https://v8--typescript-eslint.netlify.app/rules/no-empty-object-type) +- [`no-empty-object-type`](https://v8--typescript-eslint.netlify.app/rules/no-empty-object-type) - typescript-eslint@v8's [`no-restricted-types`](https://v8--typescript-eslint.netlify.app/rules/no-restricted-types) - typescript-eslint@v8's [`no-wrapper-object-types`](https://v8--typescript-eslint.netlify.app/rules/no-wrapper-object-types) diff --git a/packages/eslint-plugin/docs/rules/no-wrapper-object-types.mdx b/packages/eslint-plugin/docs/rules/no-wrapper-object-types.mdx index 355d628ea8cb..0d22df5e89fe 100644 --- a/packages/eslint-plugin/docs/rules/no-wrapper-object-types.mdx +++ b/packages/eslint-plugin/docs/rules/no-wrapper-object-types.mdx @@ -70,6 +70,6 @@ You might consider using [ESLint disable comments](https://eslint.org/docs/lates ## Related To -- [`no-empty-object-type`](https://v8--typescript-eslint.netlify.app/rules/no-empty-object-type) +- [`no-empty-object-type`](./no-empty-object-type.mdx) - [`no-restricted-types`](https://v8--typescript-eslint.netlify.app/rules/no-restricted-types) - [`no-unsafe-function-type`](https://v8--typescript-eslint.netlify.app/rules/no-unsafe-function-type) From d6a084e312ef6a90d4a6b91dafcf25126b661c52 Mon Sep 17 00:00:00 2001 From: Josh Goldberg Date: Sat, 13 Jul 2024 14:12:03 -0400 Subject: [PATCH 6/9] Remove remaining v8's --- packages/eslint-plugin/docs/rules/no-unsafe-function-type.mdx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/eslint-plugin/docs/rules/no-unsafe-function-type.mdx b/packages/eslint-plugin/docs/rules/no-unsafe-function-type.mdx index 2c79d624c78d..b8b80b133cb5 100644 --- a/packages/eslint-plugin/docs/rules/no-unsafe-function-type.mdx +++ b/packages/eslint-plugin/docs/rules/no-unsafe-function-type.mdx @@ -59,5 +59,5 @@ You might consider using [ESLint disable comments](https://eslint.org/docs/lates ## Related To - [`no-empty-object-type`](https://v8--typescript-eslint.netlify.app/rules/no-empty-object-type) -- typescript-eslint@v8's [`no-restricted-types`](https://v8--typescript-eslint.netlify.app/rules/no-restricted-types) -- typescript-eslint@v8's [`no-wrapper-object-types`](https://v8--typescript-eslint.netlify.app/rules/no-wrapper-object-types) +- [`no-restricted-types`](https://v8--typescript-eslint.netlify.app/rules/no-restricted-types) +- [`no-wrapper-object-types`](https://v8--typescript-eslint.netlify.app/rules/no-wrapper-object-types) From 64972b7c3ed0bd74926c97ecf0ba395460f6d1ce Mon Sep 17 00:00:00 2001 From: Josh Goldberg Date: Tue, 16 Jul 2024 23:11:47 -0400 Subject: [PATCH 7/9] ran yarn generate-configs --- packages/eslint-plugin/src/configs/all.ts | 2 ++ packages/eslint-plugin/src/configs/recommended-type-checked.ts | 2 ++ packages/eslint-plugin/src/configs/recommended.ts | 2 ++ packages/eslint-plugin/src/configs/strict-type-checked.ts | 2 ++ packages/eslint-plugin/src/configs/strict.ts | 2 ++ packages/typescript-eslint/src/configs/all.ts | 2 ++ .../typescript-eslint/src/configs/recommended-type-checked.ts | 2 ++ packages/typescript-eslint/src/configs/recommended.ts | 2 ++ packages/typescript-eslint/src/configs/strict-type-checked.ts | 2 ++ packages/typescript-eslint/src/configs/strict.ts | 2 ++ 10 files changed, 20 insertions(+) diff --git a/packages/eslint-plugin/src/configs/all.ts b/packages/eslint-plugin/src/configs/all.ts index 9b4f6f19a71a..2dee5a2dfb86 100644 --- a/packages/eslint-plugin/src/configs/all.ts +++ b/packages/eslint-plugin/src/configs/all.ts @@ -104,6 +104,7 @@ export = { '@typescript-eslint/no-unsafe-call': 'error', '@typescript-eslint/no-unsafe-declaration-merging': 'error', '@typescript-eslint/no-unsafe-enum-comparison': 'error', + '@typescript-eslint/no-unsafe-function-type': 'error', '@typescript-eslint/no-unsafe-member-access': 'error', '@typescript-eslint/no-unsafe-return': 'error', '@typescript-eslint/no-unsafe-unary-minus': 'error', @@ -117,6 +118,7 @@ export = { '@typescript-eslint/no-useless-constructor': 'error', '@typescript-eslint/no-useless-empty-export': 'error', '@typescript-eslint/no-var-requires': 'error', + '@typescript-eslint/no-wrapper-object-types': 'error', '@typescript-eslint/non-nullable-type-assertion-style': 'error', 'no-throw-literal': 'off', '@typescript-eslint/only-throw-error': 'error', diff --git a/packages/eslint-plugin/src/configs/recommended-type-checked.ts b/packages/eslint-plugin/src/configs/recommended-type-checked.ts index 38d36c132851..5c0b8e3a3e62 100644 --- a/packages/eslint-plugin/src/configs/recommended-type-checked.ts +++ b/packages/eslint-plugin/src/configs/recommended-type-checked.ts @@ -39,11 +39,13 @@ export = { '@typescript-eslint/no-unsafe-call': 'error', '@typescript-eslint/no-unsafe-declaration-merging': 'error', '@typescript-eslint/no-unsafe-enum-comparison': 'error', + '@typescript-eslint/no-unsafe-function-type': 'error', '@typescript-eslint/no-unsafe-member-access': 'error', '@typescript-eslint/no-unsafe-return': 'error', 'no-unused-vars': 'off', '@typescript-eslint/no-unused-vars': 'error', '@typescript-eslint/no-var-requires': 'error', + '@typescript-eslint/no-wrapper-object-types': 'error', '@typescript-eslint/prefer-as-const': 'error', 'require-await': 'off', '@typescript-eslint/require-await': 'error', diff --git a/packages/eslint-plugin/src/configs/recommended.ts b/packages/eslint-plugin/src/configs/recommended.ts index 80a607a3288f..a306208417c7 100644 --- a/packages/eslint-plugin/src/configs/recommended.ts +++ b/packages/eslint-plugin/src/configs/recommended.ts @@ -25,9 +25,11 @@ export = { '@typescript-eslint/no-this-alias': 'error', '@typescript-eslint/no-unnecessary-type-constraint': 'error', '@typescript-eslint/no-unsafe-declaration-merging': 'error', + '@typescript-eslint/no-unsafe-function-type': 'error', 'no-unused-vars': 'off', '@typescript-eslint/no-unused-vars': 'error', '@typescript-eslint/no-var-requires': 'error', + '@typescript-eslint/no-wrapper-object-types': 'error', '@typescript-eslint/prefer-as-const': 'error', '@typescript-eslint/triple-slash-reference': 'error', }, diff --git a/packages/eslint-plugin/src/configs/strict-type-checked.ts b/packages/eslint-plugin/src/configs/strict-type-checked.ts index cdce2e4962b6..907782db0234 100644 --- a/packages/eslint-plugin/src/configs/strict-type-checked.ts +++ b/packages/eslint-plugin/src/configs/strict-type-checked.ts @@ -55,6 +55,7 @@ export = { '@typescript-eslint/no-unsafe-call': 'error', '@typescript-eslint/no-unsafe-declaration-merging': 'error', '@typescript-eslint/no-unsafe-enum-comparison': 'error', + '@typescript-eslint/no-unsafe-function-type': 'error', '@typescript-eslint/no-unsafe-member-access': 'error', '@typescript-eslint/no-unsafe-return': 'error', 'no-unused-vars': 'off', @@ -62,6 +63,7 @@ export = { 'no-useless-constructor': 'off', '@typescript-eslint/no-useless-constructor': 'error', '@typescript-eslint/no-var-requires': 'error', + '@typescript-eslint/no-wrapper-object-types': 'error', 'no-throw-literal': 'off', '@typescript-eslint/only-throw-error': 'error', '@typescript-eslint/prefer-as-const': 'error', diff --git a/packages/eslint-plugin/src/configs/strict.ts b/packages/eslint-plugin/src/configs/strict.ts index 9c51d5c47348..c8eaae810e8a 100644 --- a/packages/eslint-plugin/src/configs/strict.ts +++ b/packages/eslint-plugin/src/configs/strict.ts @@ -33,11 +33,13 @@ export = { '@typescript-eslint/no-this-alias': 'error', '@typescript-eslint/no-unnecessary-type-constraint': 'error', '@typescript-eslint/no-unsafe-declaration-merging': 'error', + '@typescript-eslint/no-unsafe-function-type': 'error', 'no-unused-vars': 'off', '@typescript-eslint/no-unused-vars': 'error', 'no-useless-constructor': 'off', '@typescript-eslint/no-useless-constructor': 'error', '@typescript-eslint/no-var-requires': 'error', + '@typescript-eslint/no-wrapper-object-types': 'error', '@typescript-eslint/prefer-as-const': 'error', '@typescript-eslint/prefer-literal-enum-member': 'error', '@typescript-eslint/triple-slash-reference': 'error', diff --git a/packages/typescript-eslint/src/configs/all.ts b/packages/typescript-eslint/src/configs/all.ts index 5aee561b27ed..665cce1508a0 100644 --- a/packages/typescript-eslint/src/configs/all.ts +++ b/packages/typescript-eslint/src/configs/all.ts @@ -113,6 +113,7 @@ export default ( '@typescript-eslint/no-unsafe-call': 'error', '@typescript-eslint/no-unsafe-declaration-merging': 'error', '@typescript-eslint/no-unsafe-enum-comparison': 'error', + '@typescript-eslint/no-unsafe-function-type': 'error', '@typescript-eslint/no-unsafe-member-access': 'error', '@typescript-eslint/no-unsafe-return': 'error', '@typescript-eslint/no-unsafe-unary-minus': 'error', @@ -126,6 +127,7 @@ export default ( '@typescript-eslint/no-useless-constructor': 'error', '@typescript-eslint/no-useless-empty-export': 'error', '@typescript-eslint/no-var-requires': 'error', + '@typescript-eslint/no-wrapper-object-types': 'error', '@typescript-eslint/non-nullable-type-assertion-style': 'error', 'no-throw-literal': 'off', '@typescript-eslint/only-throw-error': 'error', diff --git a/packages/typescript-eslint/src/configs/recommended-type-checked.ts b/packages/typescript-eslint/src/configs/recommended-type-checked.ts index a21f35b51220..982b74dc3ce5 100644 --- a/packages/typescript-eslint/src/configs/recommended-type-checked.ts +++ b/packages/typescript-eslint/src/configs/recommended-type-checked.ts @@ -48,11 +48,13 @@ export default ( '@typescript-eslint/no-unsafe-call': 'error', '@typescript-eslint/no-unsafe-declaration-merging': 'error', '@typescript-eslint/no-unsafe-enum-comparison': 'error', + '@typescript-eslint/no-unsafe-function-type': 'error', '@typescript-eslint/no-unsafe-member-access': 'error', '@typescript-eslint/no-unsafe-return': 'error', 'no-unused-vars': 'off', '@typescript-eslint/no-unused-vars': 'error', '@typescript-eslint/no-var-requires': 'error', + '@typescript-eslint/no-wrapper-object-types': 'error', '@typescript-eslint/prefer-as-const': 'error', 'require-await': 'off', '@typescript-eslint/require-await': 'error', diff --git a/packages/typescript-eslint/src/configs/recommended.ts b/packages/typescript-eslint/src/configs/recommended.ts index a26db1e69f37..56c122fcf7bc 100644 --- a/packages/typescript-eslint/src/configs/recommended.ts +++ b/packages/typescript-eslint/src/configs/recommended.ts @@ -34,9 +34,11 @@ export default ( '@typescript-eslint/no-this-alias': 'error', '@typescript-eslint/no-unnecessary-type-constraint': 'error', '@typescript-eslint/no-unsafe-declaration-merging': 'error', + '@typescript-eslint/no-unsafe-function-type': 'error', 'no-unused-vars': 'off', '@typescript-eslint/no-unused-vars': 'error', '@typescript-eslint/no-var-requires': 'error', + '@typescript-eslint/no-wrapper-object-types': 'error', '@typescript-eslint/prefer-as-const': 'error', '@typescript-eslint/triple-slash-reference': 'error', }, diff --git a/packages/typescript-eslint/src/configs/strict-type-checked.ts b/packages/typescript-eslint/src/configs/strict-type-checked.ts index 7aeb158346c3..0cad212a3aee 100644 --- a/packages/typescript-eslint/src/configs/strict-type-checked.ts +++ b/packages/typescript-eslint/src/configs/strict-type-checked.ts @@ -64,6 +64,7 @@ export default ( '@typescript-eslint/no-unsafe-call': 'error', '@typescript-eslint/no-unsafe-declaration-merging': 'error', '@typescript-eslint/no-unsafe-enum-comparison': 'error', + '@typescript-eslint/no-unsafe-function-type': 'error', '@typescript-eslint/no-unsafe-member-access': 'error', '@typescript-eslint/no-unsafe-return': 'error', 'no-unused-vars': 'off', @@ -71,6 +72,7 @@ export default ( 'no-useless-constructor': 'off', '@typescript-eslint/no-useless-constructor': 'error', '@typescript-eslint/no-var-requires': 'error', + '@typescript-eslint/no-wrapper-object-types': 'error', 'no-throw-literal': 'off', '@typescript-eslint/only-throw-error': 'error', '@typescript-eslint/prefer-as-const': 'error', diff --git a/packages/typescript-eslint/src/configs/strict.ts b/packages/typescript-eslint/src/configs/strict.ts index 71615896c4dd..997f0d4b20e8 100644 --- a/packages/typescript-eslint/src/configs/strict.ts +++ b/packages/typescript-eslint/src/configs/strict.ts @@ -42,11 +42,13 @@ export default ( '@typescript-eslint/no-this-alias': 'error', '@typescript-eslint/no-unnecessary-type-constraint': 'error', '@typescript-eslint/no-unsafe-declaration-merging': 'error', + '@typescript-eslint/no-unsafe-function-type': 'error', 'no-unused-vars': 'off', '@typescript-eslint/no-unused-vars': 'error', 'no-useless-constructor': 'off', '@typescript-eslint/no-useless-constructor': 'error', '@typescript-eslint/no-var-requires': 'error', + '@typescript-eslint/no-wrapper-object-types': 'error', '@typescript-eslint/prefer-as-const': 'error', '@typescript-eslint/prefer-literal-enum-member': 'error', '@typescript-eslint/triple-slash-reference': 'error', From faa32235c3125d726f53b620fdd5486cad473397 Mon Sep 17 00:00:00 2001 From: Josh Goldberg Date: Wed, 17 Jul 2024 08:19:03 -0400 Subject: [PATCH 8/9] fix: configs --- packages/eslint-plugin/src/configs/recommended-type-checked.ts | 2 -- packages/eslint-plugin/src/configs/recommended.ts | 2 -- packages/eslint-plugin/src/configs/strict-type-checked.ts | 2 -- packages/eslint-plugin/src/configs/strict.ts | 2 -- packages/eslint-plugin/src/rules/no-unsafe-function-type.ts | 1 - packages/eslint-plugin/src/rules/no-wrapper-object-types.ts | 1 - .../typescript-eslint/src/configs/recommended-type-checked.ts | 2 -- packages/typescript-eslint/src/configs/recommended.ts | 2 -- packages/typescript-eslint/src/configs/strict-type-checked.ts | 2 -- packages/typescript-eslint/src/configs/strict.ts | 2 -- 10 files changed, 18 deletions(-) diff --git a/packages/eslint-plugin/src/configs/recommended-type-checked.ts b/packages/eslint-plugin/src/configs/recommended-type-checked.ts index 5c0b8e3a3e62..38d36c132851 100644 --- a/packages/eslint-plugin/src/configs/recommended-type-checked.ts +++ b/packages/eslint-plugin/src/configs/recommended-type-checked.ts @@ -39,13 +39,11 @@ export = { '@typescript-eslint/no-unsafe-call': 'error', '@typescript-eslint/no-unsafe-declaration-merging': 'error', '@typescript-eslint/no-unsafe-enum-comparison': 'error', - '@typescript-eslint/no-unsafe-function-type': 'error', '@typescript-eslint/no-unsafe-member-access': 'error', '@typescript-eslint/no-unsafe-return': 'error', 'no-unused-vars': 'off', '@typescript-eslint/no-unused-vars': 'error', '@typescript-eslint/no-var-requires': 'error', - '@typescript-eslint/no-wrapper-object-types': 'error', '@typescript-eslint/prefer-as-const': 'error', 'require-await': 'off', '@typescript-eslint/require-await': 'error', diff --git a/packages/eslint-plugin/src/configs/recommended.ts b/packages/eslint-plugin/src/configs/recommended.ts index a306208417c7..80a607a3288f 100644 --- a/packages/eslint-plugin/src/configs/recommended.ts +++ b/packages/eslint-plugin/src/configs/recommended.ts @@ -25,11 +25,9 @@ export = { '@typescript-eslint/no-this-alias': 'error', '@typescript-eslint/no-unnecessary-type-constraint': 'error', '@typescript-eslint/no-unsafe-declaration-merging': 'error', - '@typescript-eslint/no-unsafe-function-type': 'error', 'no-unused-vars': 'off', '@typescript-eslint/no-unused-vars': 'error', '@typescript-eslint/no-var-requires': 'error', - '@typescript-eslint/no-wrapper-object-types': 'error', '@typescript-eslint/prefer-as-const': 'error', '@typescript-eslint/triple-slash-reference': 'error', }, diff --git a/packages/eslint-plugin/src/configs/strict-type-checked.ts b/packages/eslint-plugin/src/configs/strict-type-checked.ts index 907782db0234..cdce2e4962b6 100644 --- a/packages/eslint-plugin/src/configs/strict-type-checked.ts +++ b/packages/eslint-plugin/src/configs/strict-type-checked.ts @@ -55,7 +55,6 @@ export = { '@typescript-eslint/no-unsafe-call': 'error', '@typescript-eslint/no-unsafe-declaration-merging': 'error', '@typescript-eslint/no-unsafe-enum-comparison': 'error', - '@typescript-eslint/no-unsafe-function-type': 'error', '@typescript-eslint/no-unsafe-member-access': 'error', '@typescript-eslint/no-unsafe-return': 'error', 'no-unused-vars': 'off', @@ -63,7 +62,6 @@ export = { 'no-useless-constructor': 'off', '@typescript-eslint/no-useless-constructor': 'error', '@typescript-eslint/no-var-requires': 'error', - '@typescript-eslint/no-wrapper-object-types': 'error', 'no-throw-literal': 'off', '@typescript-eslint/only-throw-error': 'error', '@typescript-eslint/prefer-as-const': 'error', diff --git a/packages/eslint-plugin/src/configs/strict.ts b/packages/eslint-plugin/src/configs/strict.ts index c8eaae810e8a..9c51d5c47348 100644 --- a/packages/eslint-plugin/src/configs/strict.ts +++ b/packages/eslint-plugin/src/configs/strict.ts @@ -33,13 +33,11 @@ export = { '@typescript-eslint/no-this-alias': 'error', '@typescript-eslint/no-unnecessary-type-constraint': 'error', '@typescript-eslint/no-unsafe-declaration-merging': 'error', - '@typescript-eslint/no-unsafe-function-type': 'error', 'no-unused-vars': 'off', '@typescript-eslint/no-unused-vars': 'error', 'no-useless-constructor': 'off', '@typescript-eslint/no-useless-constructor': 'error', '@typescript-eslint/no-var-requires': 'error', - '@typescript-eslint/no-wrapper-object-types': 'error', '@typescript-eslint/prefer-as-const': 'error', '@typescript-eslint/prefer-literal-enum-member': 'error', '@typescript-eslint/triple-slash-reference': 'error', diff --git a/packages/eslint-plugin/src/rules/no-unsafe-function-type.ts b/packages/eslint-plugin/src/rules/no-unsafe-function-type.ts index 624c038f8ff7..d96cba33bee3 100644 --- a/packages/eslint-plugin/src/rules/no-unsafe-function-type.ts +++ b/packages/eslint-plugin/src/rules/no-unsafe-function-type.ts @@ -9,7 +9,6 @@ export default createRule({ type: 'problem', docs: { description: 'Disallow using the unsafe built-in Function type', - recommended: 'recommended', }, fixable: 'code', messages: { diff --git a/packages/eslint-plugin/src/rules/no-wrapper-object-types.ts b/packages/eslint-plugin/src/rules/no-wrapper-object-types.ts index f51b6c8564b5..699a950b59cc 100644 --- a/packages/eslint-plugin/src/rules/no-wrapper-object-types.ts +++ b/packages/eslint-plugin/src/rules/no-wrapper-object-types.ts @@ -20,7 +20,6 @@ export default createRule({ type: 'problem', docs: { description: 'Disallow using confusing built-in primitive class wrappers', - recommended: 'recommended', }, fixable: 'code', messages: { diff --git a/packages/typescript-eslint/src/configs/recommended-type-checked.ts b/packages/typescript-eslint/src/configs/recommended-type-checked.ts index 982b74dc3ce5..a21f35b51220 100644 --- a/packages/typescript-eslint/src/configs/recommended-type-checked.ts +++ b/packages/typescript-eslint/src/configs/recommended-type-checked.ts @@ -48,13 +48,11 @@ export default ( '@typescript-eslint/no-unsafe-call': 'error', '@typescript-eslint/no-unsafe-declaration-merging': 'error', '@typescript-eslint/no-unsafe-enum-comparison': 'error', - '@typescript-eslint/no-unsafe-function-type': 'error', '@typescript-eslint/no-unsafe-member-access': 'error', '@typescript-eslint/no-unsafe-return': 'error', 'no-unused-vars': 'off', '@typescript-eslint/no-unused-vars': 'error', '@typescript-eslint/no-var-requires': 'error', - '@typescript-eslint/no-wrapper-object-types': 'error', '@typescript-eslint/prefer-as-const': 'error', 'require-await': 'off', '@typescript-eslint/require-await': 'error', diff --git a/packages/typescript-eslint/src/configs/recommended.ts b/packages/typescript-eslint/src/configs/recommended.ts index 56c122fcf7bc..a26db1e69f37 100644 --- a/packages/typescript-eslint/src/configs/recommended.ts +++ b/packages/typescript-eslint/src/configs/recommended.ts @@ -34,11 +34,9 @@ export default ( '@typescript-eslint/no-this-alias': 'error', '@typescript-eslint/no-unnecessary-type-constraint': 'error', '@typescript-eslint/no-unsafe-declaration-merging': 'error', - '@typescript-eslint/no-unsafe-function-type': 'error', 'no-unused-vars': 'off', '@typescript-eslint/no-unused-vars': 'error', '@typescript-eslint/no-var-requires': 'error', - '@typescript-eslint/no-wrapper-object-types': 'error', '@typescript-eslint/prefer-as-const': 'error', '@typescript-eslint/triple-slash-reference': 'error', }, diff --git a/packages/typescript-eslint/src/configs/strict-type-checked.ts b/packages/typescript-eslint/src/configs/strict-type-checked.ts index 0cad212a3aee..7aeb158346c3 100644 --- a/packages/typescript-eslint/src/configs/strict-type-checked.ts +++ b/packages/typescript-eslint/src/configs/strict-type-checked.ts @@ -64,7 +64,6 @@ export default ( '@typescript-eslint/no-unsafe-call': 'error', '@typescript-eslint/no-unsafe-declaration-merging': 'error', '@typescript-eslint/no-unsafe-enum-comparison': 'error', - '@typescript-eslint/no-unsafe-function-type': 'error', '@typescript-eslint/no-unsafe-member-access': 'error', '@typescript-eslint/no-unsafe-return': 'error', 'no-unused-vars': 'off', @@ -72,7 +71,6 @@ export default ( 'no-useless-constructor': 'off', '@typescript-eslint/no-useless-constructor': 'error', '@typescript-eslint/no-var-requires': 'error', - '@typescript-eslint/no-wrapper-object-types': 'error', 'no-throw-literal': 'off', '@typescript-eslint/only-throw-error': 'error', '@typescript-eslint/prefer-as-const': 'error', diff --git a/packages/typescript-eslint/src/configs/strict.ts b/packages/typescript-eslint/src/configs/strict.ts index 997f0d4b20e8..71615896c4dd 100644 --- a/packages/typescript-eslint/src/configs/strict.ts +++ b/packages/typescript-eslint/src/configs/strict.ts @@ -42,13 +42,11 @@ export default ( '@typescript-eslint/no-this-alias': 'error', '@typescript-eslint/no-unnecessary-type-constraint': 'error', '@typescript-eslint/no-unsafe-declaration-merging': 'error', - '@typescript-eslint/no-unsafe-function-type': 'error', 'no-unused-vars': 'off', '@typescript-eslint/no-unused-vars': 'error', 'no-useless-constructor': 'off', '@typescript-eslint/no-useless-constructor': 'error', '@typescript-eslint/no-var-requires': 'error', - '@typescript-eslint/no-wrapper-object-types': 'error', '@typescript-eslint/prefer-as-const': 'error', '@typescript-eslint/prefer-literal-enum-member': 'error', '@typescript-eslint/triple-slash-reference': 'error', From b8c810cb208514adf8f1784686e215542b54e198 Mon Sep 17 00:00:00 2001 From: Josh Goldberg Date: Thu, 18 Jul 2024 12:37:46 -0400 Subject: [PATCH 9/9] fix: snapshots --- .../schema-snapshots/no-unsafe-function-type.shot | 14 ++++++++++++++ .../schema-snapshots/no-wrapper-object-types.shot | 14 ++++++++++++++ 2 files changed, 28 insertions(+) create mode 100644 packages/eslint-plugin/tests/schema-snapshots/no-unsafe-function-type.shot create mode 100644 packages/eslint-plugin/tests/schema-snapshots/no-wrapper-object-types.shot diff --git a/packages/eslint-plugin/tests/schema-snapshots/no-unsafe-function-type.shot b/packages/eslint-plugin/tests/schema-snapshots/no-unsafe-function-type.shot new file mode 100644 index 000000000000..0317a17c3ad5 --- /dev/null +++ b/packages/eslint-plugin/tests/schema-snapshots/no-unsafe-function-type.shot @@ -0,0 +1,14 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Rule schemas should be convertible to TS types for documentation purposes no-unsafe-function-type 1`] = ` +" +# SCHEMA: + +[] + + +# TYPES: + +/** No options declared */ +type Options = [];" +`; diff --git a/packages/eslint-plugin/tests/schema-snapshots/no-wrapper-object-types.shot b/packages/eslint-plugin/tests/schema-snapshots/no-wrapper-object-types.shot new file mode 100644 index 000000000000..247f1dd2e183 --- /dev/null +++ b/packages/eslint-plugin/tests/schema-snapshots/no-wrapper-object-types.shot @@ -0,0 +1,14 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Rule schemas should be convertible to TS types for documentation purposes no-wrapper-object-types 1`] = ` +" +# SCHEMA: + +[] + + +# TYPES: + +/** No options declared */ +type Options = [];" +`;