Add utility modules
Some checks failed
CI / test (push) Has been cancelled

This commit is contained in:
2026-01-30 01:01:09 +00:00
parent c11c4b6b9d
commit 0ef343c13d

142
src/utils/typeUtils.ts Normal file
View File

@@ -0,0 +1,142 @@
import type * as TSESTree from '@typescript-eslint/typescript-estree';
export function getTypeName(node: TSESTree.Node): string | null {
switch (node.type) {
case 'TSTypeReference':
if (node.typeName.type === 'Identifier') {
return node.typeName.name;
}
break;
case 'TSQualifiedName':
if (node.left.type === 'Identifier' && node.right.type === 'Identifier') {
return `${node.left.name}.${node.right.name}`;
}
break;
case 'Identifier':
return node.name;
case 'TSInterfaceDeclaration':
return node.id.name;
case 'TSTypeAliasDeclaration':
return node.id.name;
case 'TSEnumDeclaration':
return node.id.name;
case 'ClassDeclaration':
return node.id?.name;
}
return null;
}
export function extractTypeAnnotation(node: TSESTree.Node): string {
if (node.typeAnnotation && node.typeAnnotation.typeAnnotation) {
return typeToString(node.typeAnnotation.typeAnnotation);
}
return '';
}
export function typeToString(node: TSESTree.Node): string {
switch (node.type) {
case 'TSStringKeyword':
return 'string';
case 'TSNumberKeyword':
return 'number';
case 'TSBooleanKeyword':
return 'boolean';
case 'TSNullKeyword':
return 'null';
case 'TSUndefinedKeyword':
return 'undefined';
case 'TSVoidKeyword':
return 'void';
case 'TSNeverKeyword':
return 'never';
case 'TSAnyKeyword':
return 'any';
case 'TSUnknownKeyword':
return 'unknown';
case 'TSBigIntKeyword':
return 'bigint';
case 'TSSymbolKeyword':
return 'symbol';
case 'TSArrayType':
return `${typeToString(node.elementType)}[]`;
case 'TSTupleType':
return `[${node.elementTypes.map((el: TSESTree.TSTupleElement) => typeToString(el)).join(', ')}]`;
case 'TSUnionType':
return node.types.map((t: TSESTree.Node) => typeToString(t)).join(' | ');
case 'TSIntersectionType':
return node.types.map((t: TSESTree.Node) => typeToString(t)).join(' & ');
case 'TSTypeReference':
if (node.typeName.type === 'Identifier') {
const typeArgs = node.typeParameters?.params
? `<${node.typeParameters.params.map((p: TSESTree.Node) => typeToString(p)).join(', ')}>`
: '';
return `${node.typeName.name}${typeArgs}`;
}
break;
case 'TSTypeLiteral':
return `{ ${node.members.map((m: TSESTree.Node) => typeToString(m)).join('; ')} }`;
case 'TSPropertySignature': {
const key = node.key.type === 'Identifier' ? node.key.name : typeToString(node.key);
const optional = node.optional ? '?' : '';
return `${key}${optional}: ${typeToString(node.typeAnnotation?.typeAnnotation || node)}`;
}
case 'TSCallSignatureDeclaration':
return '()';
case 'TSConstructSignatureDeclaration':
return 'new()';
case 'TSMethodSignature': {
const methodName = node.key.type === 'Identifier' ? node.key.name : typeToString(node.key);
return `${methodName}()`;
}
case 'TSQualifiedName':
return `${typeToString(node.left)}.${typeToString(node.right)}`;
case 'TSParenthesizedType':
return `(${typeToString(node.typeAnnotation)})`;
case 'TSNonNullExpression':
return `${typeToString(node.expression)}`;
case 'TSTypeQuery':
if (node.exprName.type === 'Identifier') {
return `typeof ${node.exprName.name}`;
}
break;
case 'TSMappedType': {
const typeParam = node.typeParameter.name.constraint
? `${node.typeParameter.name}: ${typeToString(node.typeParameter.constraint!)}`
: node.typeParameter.name;
const asClause = node.asClause
? ` as ${typeToString(node.asClause)}`
: '';
return `{ [${typeParam}${asClause}]${node.optional ? '?' : ''} in ${typeToString(node.typeParameter.constraint || node.typeParameter)} }`;
}
case 'TSIndexedAccessType':
return `${typeToString(node.objectType)}[${typeToString(node.indexType)}]`;
case 'TSConditionalType':
return `${typeToString(node.checkType)} extends ${typeToString(node.extendsType)} ? ${typeToString(node.trueType)} : ${typeToString(node.falseType)}`;
case 'TSInferType':
return `infer ${node.typeParameter.name}`;
case 'TSTemplateLiteralType':
return `\`${node.quasis.map((q: TSESTree.TemplateLiteral) => q.value.raw).join('')}\``;
}
return 'unknown';
}
export function isExternalModule(name: string): boolean {
return name.startsWith('@') || !name.startsWith('.') && !name.startsWith('/');
}
export function normalizeModuleName(moduleName: string, basePath: string): string {
if (isExternalModule(moduleName)) {
return moduleName;
}
return path.resolve(basePath, moduleName);
}
import * as path from 'path';
export function getNodeId(node: TSESTree.Node, filePath: string): string {
const name = getTypeName(node);
if (name) {
return `${filePath}#${name}`;
}
return `${filePath}#${node.range[0]}-${node.range[1]}`;
}