Skip to content

chore(utils): use Extract generic for ast-utils' predicates' helper functions #4545

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 10 commits into from
Aug 25, 2022
9 changes: 0 additions & 9 deletions packages/ast-spec/src/token/spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,4 @@ export * from './NumericToken/spec';
export * from './PunctuatorToken/spec';
export * from './RegularExpressionToken/spec';
export * from './StringToken/spec';
export * from './TSAbstractKeyword/spec';
export * from './TSAsyncKeyword/spec';
export * from './TSDeclareKeyword/spec';
export * from './TSExportKeyword/spec';
export * from './TSPrivateKeyword/spec';
export * from './TSProtectedKeyword/spec';
export * from './TSPublicKeyword/spec';
export * from './TSReadonlyKeyword/spec';
export * from './TSStaticKeyword/spec';
export * from './TemplateToken/spec';
10 changes: 10 additions & 0 deletions packages/ast-spec/src/type/spec.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,19 @@
export * from './TSAbstractKeyword/spec';
export * from './TSAnyKeyword/spec';
export * from './TSArrayType/spec';
export * from './TSAsyncKeyword/spec';
export * from './TSBigIntKeyword/spec';
export * from './TSBooleanKeyword/spec';
export * from './TSConditionalType/spec';
export * from './TSConstructorType/spec';
export * from './TSDeclareKeyword/spec';
export * from './TSExportKeyword/spec';
export * from './TSFunctionType/spec';
export * from './TSImportType/spec';
export * from './TSIndexedAccessType/spec';
export * from './TSInferType/spec';
export * from './TSIntersectionType/spec';
export * from './TSIntrinsicKeyword/spec';
export * from './TSLiteralType/spec';
export * from './TSMappedType/spec';
export * from './TSNamedTupleMember/spec';
Expand All @@ -17,8 +22,13 @@ export * from './TSNullKeyword/spec';
export * from './TSNumberKeyword/spec';
export * from './TSObjectKeyword/spec';
export * from './TSOptionalType/spec';
export * from './TSPrivateKeyword/spec';
export * from './TSProtectedKeyword/spec';
export * from './TSPublicKeyword/spec';
export * from './TSQualifiedName/spec';
export * from './TSReadonlyKeyword/spec';
export * from './TSRestType/spec';
export * from './TSStaticKeyword/spec';
export * from './TSStringKeyword/spec';
export * from './TSSymbolKeyword/spec';
export * from './TSTemplateLiteralType/spec';
Expand Down
14 changes: 7 additions & 7 deletions packages/ast-spec/src/unions/Modifier.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import type { TSAbstractKeyword } from '../token/TSAbstractKeyword/spec';
import type { TSAsyncKeyword } from '../token/TSAsyncKeyword/spec';
import type { TSPrivateKeyword } from '../token/TSPrivateKeyword/spec';
import type { TSProtectedKeyword } from '../token/TSProtectedKeyword/spec';
import type { TSPublicKeyword } from '../token/TSPublicKeyword/spec';
import type { TSReadonlyKeyword } from '../token/TSReadonlyKeyword/spec';
import type { TSStaticKeyword } from '../token/TSStaticKeyword/spec';
import type { TSAbstractKeyword } from '../type/TSAbstractKeyword/spec';
import type { TSAsyncKeyword } from '../type/TSAsyncKeyword/spec';
import type { TSPrivateKeyword } from '../type/TSPrivateKeyword/spec';
import type { TSProtectedKeyword } from '../type/TSProtectedKeyword/spec';
import type { TSPublicKeyword } from '../type/TSPublicKeyword/spec';
import type { TSReadonlyKeyword } from '../type/TSReadonlyKeyword/spec';
import type { TSStaticKeyword } from '../type/TSStaticKeyword/spec';

export type Modifier =
| TSAbstractKeyword
Expand Down
20 changes: 10 additions & 10 deletions packages/ast-spec/src/unions/Node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -116,27 +116,22 @@ import type { TryStatement } from '../statement/TryStatement/spec';
import type { TSExportAssignment } from '../statement/TSExportAssignment/spec';
import type { WhileStatement } from '../statement/WhileStatement/spec';
import type { WithStatement } from '../statement/WithStatement/spec';
import type { TSAbstractKeyword } from '../token/TSAbstractKeyword/spec';
import type { TSAsyncKeyword } from '../token/TSAsyncKeyword/spec';
import type { TSDeclareKeyword } from '../token/TSDeclareKeyword/spec';
import type { TSExportKeyword } from '../token/TSExportKeyword/spec';
import type { TSPrivateKeyword } from '../token/TSPrivateKeyword/spec';
import type { TSProtectedKeyword } from '../token/TSProtectedKeyword/spec';
import type { TSPublicKeyword } from '../token/TSPublicKeyword/spec';
import type { TSReadonlyKeyword } from '../token/TSReadonlyKeyword/spec';
import type { TSStaticKeyword } from '../token/TSStaticKeyword/spec';
import type { TSAbstractKeyword } from '../type/TSAbstractKeyword/spec';
import type { TSAnyKeyword } from '../type/TSAnyKeyword/spec';
import type { TSArrayType } from '../type/TSArrayType/spec';
import type { TSAsyncKeyword } from '../type/TSAsyncKeyword/spec';
import type { TSBigIntKeyword } from '../type/TSBigIntKeyword/spec';
import type { TSBooleanKeyword } from '../type/TSBooleanKeyword/spec';
import type { TSConditionalType } from '../type/TSConditionalType/spec';
import type { TSConstructorType } from '../type/TSConstructorType/spec';
import type { TSDeclareKeyword } from '../type/TSDeclareKeyword/spec';
import type { TSExportKeyword } from '../type/TSExportKeyword/spec';
import type { TSFunctionType } from '../type/TSFunctionType/spec';
import type { TSImportType } from '../type/TSImportType/spec';
import type { TSIndexedAccessType } from '../type/TSIndexedAccessType/spec';
import type { TSInferType } from '../type/TSInferType/spec';
import type { TSIntersectionType } from '../type/TSIntersectionType/spec';
import type { TSIntrinsicKeyword } from '../type/TSIntrinsicType/spec';
import type { TSIntrinsicKeyword } from '../type/TSIntrinsicKeyword/spec';
import type { TSLiteralType } from '../type/TSLiteralType/spec';
import type { TSMappedType } from '../type/TSMappedType/spec';
import type { TSNamedTupleMember } from '../type/TSNamedTupleMember/spec';
Expand All @@ -145,8 +140,13 @@ import type { TSNullKeyword } from '../type/TSNullKeyword/spec';
import type { TSNumberKeyword } from '../type/TSNumberKeyword/spec';
import type { TSObjectKeyword } from '../type/TSObjectKeyword/spec';
import type { TSOptionalType } from '../type/TSOptionalType/spec';
import type { TSPrivateKeyword } from '../type/TSPrivateKeyword/spec';
import type { TSProtectedKeyword } from '../type/TSProtectedKeyword/spec';
import type { TSPublicKeyword } from '../type/TSPublicKeyword/spec';
import type { TSQualifiedName } from '../type/TSQualifiedName/spec';
import type { TSReadonlyKeyword } from '../type/TSReadonlyKeyword/spec';
import type { TSRestType } from '../type/TSRestType/spec';
import type { TSStaticKeyword } from '../type/TSStaticKeyword/spec';
import type { TSStringKeyword } from '../type/TSStringKeyword/spec';
import type { TSSymbolKeyword } from '../type/TSSymbolKeyword/spec';
import type { TSTemplateLiteralType } from '../type/TSTemplateLiteralType/spec';
Expand Down
20 changes: 19 additions & 1 deletion packages/ast-spec/src/unions/TypeNode.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,19 @@
import type { TSAbstractKeyword } from '../type/TSAbstractKeyword/spec';
import type { TSAnyKeyword } from '../type/TSAnyKeyword/spec';
import type { TSArrayType } from '../type/TSArrayType/spec';
import type { TSAsyncKeyword } from '../type/TSAsyncKeyword/spec';
import type { TSBigIntKeyword } from '../type/TSBigIntKeyword/spec';
import type { TSBooleanKeyword } from '../type/TSBooleanKeyword/spec';
import type { TSConditionalType } from '../type/TSConditionalType/spec';
import type { TSConstructorType } from '../type/TSConstructorType/spec';
import type { TSDeclareKeyword } from '../type/TSDeclareKeyword/spec';
import type { TSExportKeyword } from '../type/TSExportKeyword/spec';
import type { TSFunctionType } from '../type/TSFunctionType/spec';
import type { TSImportType } from '../type/TSImportType/spec';
import type { TSIndexedAccessType } from '../type/TSIndexedAccessType/spec';
import type { TSInferType } from '../type/TSInferType/spec';
import type { TSIntersectionType } from '../type/TSIntersectionType/spec';
import type { TSIntrinsicKeyword } from '../type/TSIntrinsicType/spec';
import type { TSIntrinsicKeyword } from '../type/TSIntrinsicKeyword/spec';
import type { TSLiteralType } from '../type/TSLiteralType/spec';
import type { TSMappedType } from '../type/TSMappedType/spec';
import type { TSNamedTupleMember } from '../type/TSNamedTupleMember/spec';
Expand All @@ -18,7 +22,12 @@ import type { TSNullKeyword } from '../type/TSNullKeyword/spec';
import type { TSNumberKeyword } from '../type/TSNumberKeyword/spec';
import type { TSObjectKeyword } from '../type/TSObjectKeyword/spec';
import type { TSOptionalType } from '../type/TSOptionalType/spec';
import type { TSPrivateKeyword } from '../type/TSPrivateKeyword/spec';
import type { TSProtectedKeyword } from '../type/TSProtectedKeyword/spec';
import type { TSPublicKeyword } from '../type/TSPublicKeyword/spec';
import type { TSReadonlyKeyword } from '../type/TSReadonlyKeyword/spec';
import type { TSRestType } from '../type/TSRestType/spec';
import type { TSStaticKeyword } from '../type/TSStaticKeyword/spec';
import type { TSStringKeyword } from '../type/TSStringKeyword/spec';
import type { TSSymbolKeyword } from '../type/TSSymbolKeyword/spec';
import type { TSTemplateLiteralType } from '../type/TSTemplateLiteralType/spec';
Expand All @@ -35,12 +44,16 @@ import type { TSUnknownKeyword } from '../type/TSUnknownKeyword/spec';
import type { TSVoidKeyword } from '../type/TSVoidKeyword/spec';

export type TypeNode =
| TSAbstractKeyword
| TSAnyKeyword
| TSArrayType
| TSAsyncKeyword
| TSBigIntKeyword
| TSBooleanKeyword
| TSConditionalType
| TSConstructorType
| TSDeclareKeyword
| TSExportKeyword
| TSFunctionType
| TSImportType
| TSIndexedAccessType
Expand All @@ -55,7 +68,12 @@ export type TypeNode =
| TSNumberKeyword
| TSObjectKeyword
| TSOptionalType
| TSPrivateKeyword
| TSProtectedKeyword
| TSPublicKeyword
| TSReadonlyKeyword
| TSRestType
| TSStaticKeyword
| TSStringKeyword
| TSSymbolKeyword
| TSTemplateLiteralType
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,9 +75,18 @@ function getGroup(node: TSESTree.TypeNode): Group {
return Group.union;

// These types should never occur as part of a union/intersection
case AST_NODE_TYPES.TSAbstractKeyword:
case AST_NODE_TYPES.TSAsyncKeyword:
case AST_NODE_TYPES.TSDeclareKeyword:
case AST_NODE_TYPES.TSExportKeyword:
case AST_NODE_TYPES.TSNamedTupleMember:
case AST_NODE_TYPES.TSOptionalType:
case AST_NODE_TYPES.TSPrivateKeyword:
case AST_NODE_TYPES.TSProtectedKeyword:
case AST_NODE_TYPES.TSPublicKeyword:
case AST_NODE_TYPES.TSReadonlyKeyword:
case AST_NODE_TYPES.TSRestType:
case AST_NODE_TYPES.TSStaticKeyword:
case AST_NODE_TYPES.TSTypePredicate:
/* istanbul ignore next */
throw new Error(`Unexpected Type ${node.type}`);
Expand Down
41 changes: 20 additions & 21 deletions packages/utils/src/ast-utils/helpers.ts
Original file line number Diff line number Diff line change
@@ -1,75 +1,74 @@
import { AST_NODE_TYPES, AST_TOKEN_TYPES, TSESTree } from '../ts-estree';

type ObjectEntry<BaseType> = [keyof BaseType, BaseType[keyof BaseType]];
type ObjectEntry<BaseType> = BaseType extends unknown
? [keyof BaseType, BaseType[keyof BaseType]]
: never;
type ObjectEntries<BaseType> = Array<ObjectEntry<BaseType>>;

export const isNodeOfType =
<NodeType extends AST_NODE_TYPES>(nodeType: NodeType) =>
(
node: TSESTree.Node | null | undefined,
): node is TSESTree.Node & { type: NodeType } =>
): node is Extract<TSESTree.Node, { type: NodeType }> =>
node?.type === nodeType;

export const isNodeOfTypes =
<NodeTypes extends readonly AST_NODE_TYPES[]>(nodeTypes: NodeTypes) =>
(
node: TSESTree.Node | null | undefined,
): node is TSESTree.Node & { type: NodeTypes[number] } =>
): node is Extract<TSESTree.Node, { type: NodeTypes[number] }> =>
!!node && nodeTypes.includes(node.type);

export const isNodeOfTypeWithConditions = <
NodeType extends AST_NODE_TYPES,
Conditions extends Partial<TSESTree.Node & { type: NodeType }>,
ExtractedNode extends Extract<TSESTree.Node, { type: NodeType }>,
Conditions extends Partial<ExtractedNode>,
>(
nodeType: NodeType,
conditions: Conditions,
): ((
node: TSESTree.Node | null | undefined,
) => node is TSESTree.Node & { type: NodeType } & Conditions) => {
) => node is ExtractedNode & Conditions) => {
const entries = Object.entries(conditions) as ObjectEntries<TSESTree.Node>;

return (
node: TSESTree.Node | null | undefined,
): node is TSESTree.Node & { type: NodeType } & Conditions =>
): node is ExtractedNode & Conditions =>
node?.type === nodeType &&
entries.every(([key, value]) => node[key] === value);
entries.every(([key, value]) => node[key as keyof TSESTree.Node] === value);
};

export const isTokenOfTypeWithConditions = <
TokenType extends AST_TOKEN_TYPES,
ExtractedToken extends Extract<TSESTree.Token, { type: TokenType }>,
Conditions extends Partial<TSESTree.Token & { type: TokenType }>,
>(
tokenType: TokenType,
conditions: Conditions,
): ((
token: TSESTree.Token | null | undefined,
) => token is TSESTree.Token & { type: TokenType } & Conditions) => {
) => token is ExtractedToken & Conditions) => {
const entries = Object.entries(conditions) as ObjectEntries<TSESTree.Token>;

return (
token: TSESTree.Token | null | undefined,
): token is TSESTree.Token & { type: TokenType } & Conditions =>
): token is ExtractedToken & Conditions =>
token?.type === tokenType &&
entries.every(([key, value]) => token[key] === value);
entries.every(
([key, value]) => token[key as keyof TSESTree.Token] === value,
);
};

export const isNotTokenOfTypeWithConditions =
<
TokenType extends AST_TOKEN_TYPES,
Conditions extends Partial<TSESTree.Token & { type: TokenType }>,
ExtractedToken extends Extract<TSESTree.Token, { type: TokenType }>,
Conditions extends Partial<ExtractedToken>,
>(
tokenType: TokenType,
conditions: Conditions,
): ((
token: TSESTree.Token | null | undefined,
) => token is Exclude<
TSESTree.Token,
TSESTree.Token & { type: TokenType } & Conditions
>) =>
(
token,
): token is Exclude<
TSESTree.Token,
TSESTree.Token & { type: TokenType } & Conditions
> =>
) => token is Exclude<TSESTree.Token, ExtractedToken & Conditions>) =>
(token): token is Exclude<TSESTree.Token, ExtractedToken & Conditions> =>
!isTokenOfTypeWithConditions(tokenType, conditions)(token);