From 5ece2d90b55ed08c630acaab054d9021f9bfaa44 Mon Sep 17 00:00:00 2001 From: Lisa Nguyen Date: Mon, 26 Apr 2021 14:29:34 +1000 Subject: [PATCH] feat(experimental-utils): moved types eslint-plugin util to experimental-utils package --- packages/eslint-plugin/src/util/index.ts | 2 +- .../src/eslint-utils/index.ts | 1 + .../src/eslint-utils}/types.ts | 2 +- .../eslint-utils}/isUnsafeAssignment.test.ts | 59 ++++++++++++------- .../typings/typescript.d.ts | 33 +++++++++++ 5 files changed, 75 insertions(+), 22 deletions(-) rename packages/{eslint-plugin/src/util => experimental-utils/src/eslint-utils}/types.ts (99%) rename packages/{eslint-plugin/tests/util => experimental-utils/tests/eslint-utils}/isUnsafeAssignment.test.ts (74%) create mode 100644 packages/experimental-utils/typings/typescript.d.ts diff --git a/packages/eslint-plugin/src/util/index.ts b/packages/eslint-plugin/src/util/index.ts index 4c028489523..4842e84facd 100644 --- a/packages/eslint-plugin/src/util/index.ts +++ b/packages/eslint-plugin/src/util/index.ts @@ -12,7 +12,7 @@ export * from './nullThrows'; export * from './objectIterators'; export * from './propertyTypes'; export * from './requiresQuoting'; -export * from './types'; +export * from '@typescript-eslint/experimental-utils/dist/eslint-utils/types'; // this is done for convenience - saves migrating all of the old rules const { applyDefault, deepMerge, isObjectNotArray, getParserServices } = diff --git a/packages/experimental-utils/src/eslint-utils/index.ts b/packages/experimental-utils/src/eslint-utils/index.ts index bbbe8df2709..2381db1d373 100644 --- a/packages/experimental-utils/src/eslint-utils/index.ts +++ b/packages/experimental-utils/src/eslint-utils/index.ts @@ -5,3 +5,4 @@ export * from './InferTypesFromRule'; export * from './RuleCreator'; export * from './RuleTester'; export * from './deepMerge'; +export * from './types'; diff --git a/packages/eslint-plugin/src/util/types.ts b/packages/experimental-utils/src/eslint-utils/types.ts similarity index 99% rename from packages/eslint-plugin/src/util/types.ts rename to packages/experimental-utils/src/eslint-utils/types.ts index 089620e702a..5da17a5e413 100644 --- a/packages/eslint-plugin/src/util/types.ts +++ b/packages/experimental-utils/src/eslint-utils/types.ts @@ -19,7 +19,7 @@ import { } from 'tsutils'; import * as ts from 'typescript'; -const log = debug('typescript-eslint:eslint-plugin:utils:types'); +const log = debug('typescript-eslint:experimental-utils:eslint-utils:types'); /** * Checks if the given type is either an array type, diff --git a/packages/eslint-plugin/tests/util/isUnsafeAssignment.test.ts b/packages/experimental-utils/tests/eslint-utils/isUnsafeAssignment.test.ts similarity index 74% rename from packages/eslint-plugin/tests/util/isUnsafeAssignment.test.ts rename to packages/experimental-utils/tests/eslint-utils/isUnsafeAssignment.test.ts index 1d4946a964d..709fc91c11b 100644 --- a/packages/eslint-plugin/tests/util/isUnsafeAssignment.test.ts +++ b/packages/experimental-utils/tests/eslint-utils/isUnsafeAssignment.test.ts @@ -1,9 +1,8 @@ import * as ts from 'typescript'; -import { TSESTree } from '@typescript-eslint/experimental-utils'; import { parseForESLint } from '@typescript-eslint/parser'; +import { getFixturesRootDir } from '@typescript-eslint/eslint-plugin/tests/RuleTester'; import path from 'path'; -import { getFixturesRootDir } from '../RuleTester'; -import { isUnsafeAssignment } from '../../src/util/types'; +import { ESLintUtils, TSESTree } from '../../src'; describe('isUnsafeAssignment', () => { const rootDir = getFixturesRootDir(); @@ -38,7 +37,7 @@ describe('isUnsafeAssignment', () => { describe('unsafe', () => { function expectTypesAre( - result: ReturnType, + result: ReturnType, checker: ts.TypeChecker, senderStr: string, receiverStr: string, @@ -56,7 +55,7 @@ describe('isUnsafeAssignment', () => { ); expectTypesAre( - isUnsafeAssignment(sender, receiver, checker, null), + ESLintUtils.isUnsafeAssignment(sender, receiver, checker, null), checker, 'any', 'string', @@ -69,7 +68,7 @@ describe('isUnsafeAssignment', () => { ); expectTypesAre( - isUnsafeAssignment(sender, receiver, checker, null), + ESLintUtils.isUnsafeAssignment(sender, receiver, checker, null), checker, 'Set', 'Set', @@ -82,7 +81,7 @@ describe('isUnsafeAssignment', () => { ); expectTypesAre( - isUnsafeAssignment(sender, receiver, checker, null), + ESLintUtils.isUnsafeAssignment(sender, receiver, checker, null), checker, 'Map', 'Map', @@ -95,7 +94,7 @@ describe('isUnsafeAssignment', () => { ); expectTypesAre( - isUnsafeAssignment(sender, receiver, checker, null), + ESLintUtils.isUnsafeAssignment(sender, receiver, checker, null), checker, 'Set', 'Set', @@ -108,7 +107,7 @@ describe('isUnsafeAssignment', () => { ); expectTypesAre( - isUnsafeAssignment(sender, receiver, checker, null), + ESLintUtils.isUnsafeAssignment(sender, receiver, checker, null), checker, 'Set>>', 'Set>>', @@ -122,13 +121,17 @@ describe('isUnsafeAssignment', () => { 'const test: string = "";', ); - expect(isUnsafeAssignment(sender, receiver, checker, null)).toBeFalsy(); + expect( + ESLintUtils.isUnsafeAssignment(sender, receiver, checker, null), + ).toBeFalsy(); }); it('non-any to a any', () => { const { sender, receiver, checker } = getTypes('const test: any = "";'); - expect(isUnsafeAssignment(sender, receiver, checker, null)).toBeFalsy(); + expect( + ESLintUtils.isUnsafeAssignment(sender, receiver, checker, null), + ).toBeFalsy(); }); it('non-any in a generic position to a non-any', () => { @@ -136,7 +139,9 @@ describe('isUnsafeAssignment', () => { 'const test: Set = new Set();', ); - expect(isUnsafeAssignment(sender, receiver, checker, null)).toBeFalsy(); + expect( + ESLintUtils.isUnsafeAssignment(sender, receiver, checker, null), + ).toBeFalsy(); }); it('non-any in a generic position to a non-any (multiple generics)', () => { @@ -144,7 +149,9 @@ describe('isUnsafeAssignment', () => { 'const test: Map = new Map();', ); - expect(isUnsafeAssignment(sender, receiver, checker, null)).toBeFalsy(); + expect( + ESLintUtils.isUnsafeAssignment(sender, receiver, checker, null), + ).toBeFalsy(); }); it('non-any[] in a generic position to a non-any[]', () => { @@ -152,7 +159,9 @@ describe('isUnsafeAssignment', () => { 'const test: Set = new Set();', ); - expect(isUnsafeAssignment(sender, receiver, checker, null)).toBeFalsy(); + expect( + ESLintUtils.isUnsafeAssignment(sender, receiver, checker, null), + ).toBeFalsy(); }); it('non-any in a generic position to a non-any (nested)', () => { @@ -160,7 +169,9 @@ describe('isUnsafeAssignment', () => { 'const test: Set>> = new Set>>();', ); - expect(isUnsafeAssignment(sender, receiver, checker, null)).toBeFalsy(); + expect( + ESLintUtils.isUnsafeAssignment(sender, receiver, checker, null), + ).toBeFalsy(); }); it('non-any in a generic position to a any (nested)', () => { @@ -168,7 +179,9 @@ describe('isUnsafeAssignment', () => { 'const test: Set>> = new Set>>();', ); - expect(isUnsafeAssignment(sender, receiver, checker, null)).toBeFalsy(); + expect( + ESLintUtils.isUnsafeAssignment(sender, receiver, checker, null), + ).toBeFalsy(); }); it('any to a unknown', () => { @@ -176,7 +189,9 @@ describe('isUnsafeAssignment', () => { 'const test: unknown = [] as any;', ); - expect(isUnsafeAssignment(sender, receiver, checker, null)).toBeFalsy(); + expect( + ESLintUtils.isUnsafeAssignment(sender, receiver, checker, null), + ).toBeFalsy(); }); it('any[] in a generic position to a unknown[]', () => { @@ -184,7 +199,9 @@ describe('isUnsafeAssignment', () => { 'const test: unknown[] = [] as any[]', ); - expect(isUnsafeAssignment(sender, receiver, checker, null)).toBeFalsy(); + expect( + ESLintUtils.isUnsafeAssignment(sender, receiver, checker, null), + ).toBeFalsy(); }); it('any in a generic position to a unknown (nested)', () => { @@ -192,7 +209,9 @@ describe('isUnsafeAssignment', () => { 'const test: Set>> = new Set>>();', ); - expect(isUnsafeAssignment(sender, receiver, checker, null)).toBeFalsy(); + expect( + ESLintUtils.isUnsafeAssignment(sender, receiver, checker, null), + ).toBeFalsy(); }); // https://github.com/typescript-eslint/typescript-eslint/issues/2109 @@ -202,7 +221,7 @@ describe('isUnsafeAssignment', () => { ); expect( - isUnsafeAssignment(sender, receiver, checker, senderNode), + ESLintUtils.isUnsafeAssignment(sender, receiver, checker, senderNode), ).toBeFalsy(); }); }); diff --git a/packages/experimental-utils/typings/typescript.d.ts b/packages/experimental-utils/typings/typescript.d.ts new file mode 100644 index 00000000000..73304155ee7 --- /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; + } +}