diff --git a/packages/eslint-plugin/src/rules/prefer-readonly-parameter-types.ts b/packages/eslint-plugin/src/rules/prefer-readonly-parameter-types.ts index fdf48395eae5..da13a0657e78 100644 --- a/packages/eslint-plugin/src/rules/prefer-readonly-parameter-types.ts +++ b/packages/eslint-plugin/src/rules/prefer-readonly-parameter-types.ts @@ -1,6 +1,7 @@ import { TSESTree, AST_NODE_TYPES, + ESLintUtils, } from '@typescript-eslint/experimental-utils'; import * as util from '../util'; @@ -8,7 +9,7 @@ type Options = [ { checkParameterProperties?: boolean; ignoreInferredTypes?: boolean; - } & util.ReadonlynessOptions, + } & ESLintUtils.ReadonlynessOptions, ]; type MessageIds = 'shouldBeReadonly'; @@ -34,7 +35,7 @@ export default util.createRule({ ignoreInferredTypes: { type: 'boolean', }, - ...util.readonlynessOptionsSchema.properties, + ...ESLintUtils.readonlynessOptionsSchema.properties, }, }, ], @@ -46,7 +47,7 @@ export default util.createRule({ { checkParameterProperties: true, ignoreInferredTypes: false, - ...util.readonlynessOptionsDefaults, + ...ESLintUtils.readonlynessOptionsDefaults, }, ], create(context, options) { @@ -98,7 +99,7 @@ export default util.createRule({ const tsNode = esTreeNodeToTSNodeMap.get(actualParam); const type = checker.getTypeAtLocation(tsNode); - const isReadOnly = util.isTypeReadonly(checker, type, { + const isReadOnly = ESLintUtils.isTypeReadonly(checker, type, { treatMethodsAsReadonly: treatMethodsAsReadonly!, }); diff --git a/packages/eslint-plugin/src/util/explicitReturnTypeUtils.ts b/packages/eslint-plugin/src/util/explicitReturnTypeUtils.ts index c05d6c6dab35..a4d4f92f6ddd 100644 --- a/packages/eslint-plugin/src/util/explicitReturnTypeUtils.ts +++ b/packages/eslint-plugin/src/util/explicitReturnTypeUtils.ts @@ -3,9 +3,14 @@ import { AST_NODE_TYPES, TSESLint, } from '@typescript-eslint/experimental-utils'; -import { isTypeAssertion, isConstructor, isSetter } from './astUtils'; -import { getFunctionHeadLoc } from './getFunctionHeadLoc'; -import { nullThrows, NullThrowsReasons } from './nullThrows'; +import { + isTypeAssertion, + isConstructor, + isSetter, + getFunctionHeadLoc, + nullThrows, + NullThrowsReasons, +} from '.'; type FunctionExpression = | TSESTree.ArrowFunctionExpression diff --git a/packages/eslint-plugin/src/util/index.ts b/packages/eslint-plugin/src/util/index.ts index 4c0284895235..fafd43cded0a 100644 --- a/packages/eslint-plugin/src/util/index.ts +++ b/packages/eslint-plugin/src/util/index.ts @@ -6,17 +6,21 @@ export * from './createRule'; export * from './getFunctionHeadLoc'; export * from './getThisExpression'; export * from './getWrappingFixer'; -export * from './isTypeReadonly'; export * from './misc'; -export * from './nullThrows'; export * from './objectIterators'; -export * from './propertyTypes'; export * from './requiresQuoting'; export * from './types'; // this is done for convenience - saves migrating all of the old rules -const { applyDefault, deepMerge, isObjectNotArray, getParserServices } = - ESLintUtils; +const { + applyDefault, + deepMerge, + isObjectNotArray, + getParserServices, + getTypeOfPropertyOfName, + nullThrows, + NullThrowsReasons, +} = ESLintUtils; type InferMessageIdsTypeFromRule = ESLintUtils.InferMessageIdsTypeFromRule; type InferOptionsTypeFromRule = ESLintUtils.InferOptionsTypeFromRule; @@ -26,6 +30,9 @@ export { deepMerge, isObjectNotArray, getParserServices, + getTypeOfPropertyOfName, + nullThrows, + NullThrowsReasons, InferMessageIdsTypeFromRule, InferOptionsTypeFromRule, }; diff --git a/packages/experimental-utils/package.json b/packages/experimental-utils/package.json index 779d7f1e61b6..4f73792b24f6 100644 --- a/packages/experimental-utils/package.json +++ b/packages/experimental-utils/package.json @@ -44,7 +44,8 @@ "@typescript-eslint/types": "4.30.0", "@typescript-eslint/typescript-estree": "4.30.0", "eslint-scope": "^5.1.1", - "eslint-utils": "^3.0.0" + "eslint-utils": "^3.0.0", + "tsutils": "^3.21.0" }, "peerDependencies": { "eslint": "*" diff --git a/packages/experimental-utils/src/eslint-utils/index.ts b/packages/experimental-utils/src/eslint-utils/index.ts index bbbe8df2709f..d1448ed508d2 100644 --- a/packages/experimental-utils/src/eslint-utils/index.ts +++ b/packages/experimental-utils/src/eslint-utils/index.ts @@ -5,3 +5,6 @@ export * from './InferTypesFromRule'; export * from './RuleCreator'; export * from './RuleTester'; export * from './deepMerge'; +export * from './isTypeReadonly'; +export * from './propertyTypes'; +export * from './nullThrows'; diff --git a/packages/eslint-plugin/src/util/isTypeReadonly.ts b/packages/experimental-utils/src/eslint-utils/isTypeReadonly.ts similarity index 100% rename from packages/eslint-plugin/src/util/isTypeReadonly.ts rename to packages/experimental-utils/src/eslint-utils/isTypeReadonly.ts diff --git a/packages/eslint-plugin/src/util/nullThrows.ts b/packages/experimental-utils/src/eslint-utils/nullThrows.ts similarity index 100% rename from packages/eslint-plugin/src/util/nullThrows.ts rename to packages/experimental-utils/src/eslint-utils/nullThrows.ts diff --git a/packages/eslint-plugin/src/util/propertyTypes.ts b/packages/experimental-utils/src/eslint-utils/propertyTypes.ts similarity index 100% rename from packages/eslint-plugin/src/util/propertyTypes.ts rename to packages/experimental-utils/src/eslint-utils/propertyTypes.ts diff --git a/packages/experimental-utils/typings/typescript.d.ts b/packages/experimental-utils/typings/typescript.d.ts new file mode 100644 index 000000000000..73304155ee74 --- /dev/null +++ b/packages/experimental-utils/typings/typescript.d.ts @@ -0,0 +1,33 @@ +import 'typescript'; + +declare module 'typescript' { + interface TypeChecker { + // internal TS APIs + + /** + * @returns `true` if the given type is an array type: + * - `Array` + * - `ReadonlyArray` + * - `foo[]` + * - `readonly foo[]` + */ + isArrayType(type: Type): type is TypeReference; + /** + * @returns `true` if the given type is a tuple type: + * - `[foo]` + * - `readonly [foo]` + */ + isTupleType(type: Type): type is TupleTypeReference; + /** + * Return the type of the given property in the given type, or undefined if no such property exists + */ + getTypeOfPropertyOfType(type: Type, propertyName: string): Type | undefined; + } + + interface Type { + /** + * If the type is `any`, and this is set to "error", then TS was unable to resolve the type + */ + intrinsicName?: string; + } +}