Skip to content

Commit

Permalink
feat(experimental-utils): moved types eslint-plugin util to experimen…
Browse files Browse the repository at this point in the history
…tal-utils package
  • Loading branch information
lnguyenfln authored and detljh committed Jun 18, 2021
1 parent a2f1dfb commit 5ece2d9
Show file tree
Hide file tree
Showing 5 changed files with 75 additions and 22 deletions.
2 changes: 1 addition & 1 deletion packages/eslint-plugin/src/util/index.ts
Expand Up @@ -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 } =
Expand Down
1 change: 1 addition & 0 deletions packages/experimental-utils/src/eslint-utils/index.ts
Expand Up @@ -5,3 +5,4 @@ export * from './InferTypesFromRule';
export * from './RuleCreator';
export * from './RuleTester';
export * from './deepMerge';
export * from './types';
Expand Up @@ -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,
Expand Down
@@ -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();
Expand Down Expand Up @@ -38,7 +37,7 @@ describe('isUnsafeAssignment', () => {

describe('unsafe', () => {
function expectTypesAre(
result: ReturnType<typeof isUnsafeAssignment>,
result: ReturnType<typeof ESLintUtils.isUnsafeAssignment>,
checker: ts.TypeChecker,
senderStr: string,
receiverStr: string,
Expand All @@ -56,7 +55,7 @@ describe('isUnsafeAssignment', () => {
);

expectTypesAre(
isUnsafeAssignment(sender, receiver, checker, null),
ESLintUtils.isUnsafeAssignment(sender, receiver, checker, null),
checker,
'any',
'string',
Expand All @@ -69,7 +68,7 @@ describe('isUnsafeAssignment', () => {
);

expectTypesAre(
isUnsafeAssignment(sender, receiver, checker, null),
ESLintUtils.isUnsafeAssignment(sender, receiver, checker, null),
checker,
'Set<any>',
'Set<string>',
Expand All @@ -82,7 +81,7 @@ describe('isUnsafeAssignment', () => {
);

expectTypesAre(
isUnsafeAssignment(sender, receiver, checker, null),
ESLintUtils.isUnsafeAssignment(sender, receiver, checker, null),
checker,
'Map<string, any>',
'Map<string, string>',
Expand All @@ -95,7 +94,7 @@ describe('isUnsafeAssignment', () => {
);

expectTypesAre(
isUnsafeAssignment(sender, receiver, checker, null),
ESLintUtils.isUnsafeAssignment(sender, receiver, checker, null),
checker,
'Set<any[]>',
'Set<string[]>',
Expand All @@ -108,7 +107,7 @@ describe('isUnsafeAssignment', () => {
);

expectTypesAre(
isUnsafeAssignment(sender, receiver, checker, null),
ESLintUtils.isUnsafeAssignment(sender, receiver, checker, null),
checker,
'Set<Set<Set<any>>>',
'Set<Set<Set<string>>>',
Expand All @@ -122,77 +121,97 @@ 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', () => {
const { sender, receiver, checker } = getTypes(
'const test: Set<string> = new Set<string>();',
);

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)', () => {
const { sender, receiver, checker } = getTypes(
'const test: Map<string, string> = new Map<string, string>();',
);

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[]', () => {
const { sender, receiver, checker } = getTypes(
'const test: Set<string[]> = new Set<string[]>();',
);

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)', () => {
const { sender, receiver, checker } = getTypes(
'const test: Set<Set<Set<string>>> = new Set<Set<Set<string>>>();',
);

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)', () => {
const { sender, receiver, checker } = getTypes(
'const test: Set<Set<Set<any>>> = new Set<Set<Set<string>>>();',
);

expect(isUnsafeAssignment(sender, receiver, checker, null)).toBeFalsy();
expect(
ESLintUtils.isUnsafeAssignment(sender, receiver, checker, null),
).toBeFalsy();
});

it('any to a unknown', () => {
const { sender, receiver, checker } = getTypes(
'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[]', () => {
const { sender, receiver, checker } = getTypes(
'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)', () => {
const { sender, receiver, checker } = getTypes(
'const test: Set<Set<Set<unknown>>> = new Set<Set<Set<any>>>();',
);

expect(isUnsafeAssignment(sender, receiver, checker, null)).toBeFalsy();
expect(
ESLintUtils.isUnsafeAssignment(sender, receiver, checker, null),
).toBeFalsy();
});

// https://github.com/typescript-eslint/typescript-eslint/issues/2109
Expand All @@ -202,7 +221,7 @@ describe('isUnsafeAssignment', () => {
);

expect(
isUnsafeAssignment(sender, receiver, checker, senderNode),
ESLintUtils.isUnsafeAssignment(sender, receiver, checker, senderNode),
).toBeFalsy();
});
});
Expand Down
33 changes: 33 additions & 0 deletions 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<foo>`
* - `ReadonlyArray<foo>`
* - `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;
}
}

0 comments on commit 5ece2d9

Please sign in to comment.