Skip to content

⬅️ Back to Table of Contents

📄 TypeVisitor

📊 Analysis Summary

Metric Count
🔧 Functions 24
🧱 Classes 1
📦 Imports 8

📚 Table of Contents

🛠️ File Location:

📂 packages/scope-manager/src/referencer/TypeVisitor.ts

📦 Imports

Name Source
TSESTree @typescript-eslint/types
AST_NODE_TYPES @typescript-eslint/types
Scope ../scope
Referencer ./Referencer
ParameterDefinition ../definition
TypeDefinition ../definition
ScopeType ../scope
Visitor ./Visitor

Functions

TypeVisitor.visit(referencer: Referencer, node: TSESTree.Node): void

Parameters:

  • referencer Referencer
  • node TSESTree.Node

Returns: void

Calls:

  • typeReferencer.visit
Code
static visit(referencer: Referencer, node: TSESTree.Node): void {
    const typeReferencer = new TypeVisitor(referencer);
    typeReferencer.visit(node);
  }

TypeVisitor.visitFunctionType(node: | TSESTree.TSCallSignatureDeclaration |…): void

Parameters:

  • node | TSESTree.TSCallSignatureDeclaration | TSESTree.TSConstructorType | TSESTree.TSConstructSignatureDeclaration | TSESTree.TSFunctionType | TSESTree.TSMethodSignature

Returns: void

Calls:

  • this.#referencer.scopeManager.nestFunctionTypeScope
  • this.visit
  • this.visitPattern
  • this.#referencer .currentScope() .defineIdentifier
  • this.#referencer.close

Internal Comments:

// arguments and type parameters can only be referenced from within the function (x6)
// a parameter name creates a value type variable which can be referenced later via typeof arg (x7)
// there are a few special cases where the type annotation is owned by the parameter, not the pattern
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition

Code
protected visitFunctionType(
    node:
      | TSESTree.TSCallSignatureDeclaration
      | TSESTree.TSConstructorType
      | TSESTree.TSConstructSignatureDeclaration
      | TSESTree.TSFunctionType
      | TSESTree.TSMethodSignature,
  ): void {
    // arguments and type parameters can only be referenced from within the function
    this.#referencer.scopeManager.nestFunctionTypeScope(node);
    this.visit(node.typeParameters);

    for (const param of node.params) {
      let didVisitAnnotation = false;
      this.visitPattern(param, (pattern, info) => {
        // a parameter name creates a value type variable which can be referenced later via typeof arg
        this.#referencer
          .currentScope()
          .defineIdentifier(
            pattern,
            new ParameterDefinition(pattern, node, info.rest),
          );

        if (pattern.typeAnnotation) {
          this.visit(pattern.typeAnnotation);
          didVisitAnnotation = true;
        }
      });

      // there are a few special cases where the type annotation is owned by the parameter, not the pattern
      // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
      if (!didVisitAnnotation && 'typeAnnotation' in param) {
        this.visit(param.typeAnnotation);
      }
    }
    this.visit(node.returnType);

    this.#referencer.close(node);
  }

TypeVisitor.visitPropertyKey(node: TSESTree.TSMethodSignature | TSESTree.T…): void

Parameters:

  • node TSESTree.TSMethodSignature | TSESTree.TSPropertySignature

Returns: void

Calls:

  • this.#referencer.visit

Internal Comments:

// computed members are treated as value references, and TS expects they have a literal type (x5)

Code
protected visitPropertyKey(
    node: TSESTree.TSMethodSignature | TSESTree.TSPropertySignature,
  ): void {
    if (!node.computed) {
      return;
    }
    // computed members are treated as value references, and TS expects they have a literal type
    this.#referencer.visit(node.key);
  }

TypeVisitor.Identifier(node: TSESTree.Identifier): void

Parameters:

  • node TSESTree.Identifier

Returns: void

Calls:

  • this.#referencer.currentScope().referenceType
Code
protected Identifier(node: TSESTree.Identifier): void {
    this.#referencer.currentScope().referenceType(node);
  }

TypeVisitor.MemberExpression(node: TSESTree.MemberExpression): void

Parameters:

  • node TSESTree.MemberExpression

Returns: void

Calls:

  • this.visit
Code
protected MemberExpression(node: TSESTree.MemberExpression): void {
    this.visit(node.object);
    // don't visit the property
  }

TypeVisitor.TSCallSignatureDeclaration(node: TSESTree.TSCallSignatureDeclaration): void

Parameters:

  • node TSESTree.TSCallSignatureDeclaration

Returns: void

Calls:

  • this.visitFunctionType
Code
protected TSCallSignatureDeclaration(
    node: TSESTree.TSCallSignatureDeclaration,
  ): void {
    this.visitFunctionType(node);
  }

TypeVisitor.TSConditionalType(node: TSESTree.TSConditionalType): void

Parameters:

  • node TSESTree.TSConditionalType

Returns: void

Calls:

  • this.#referencer.scopeManager.nestConditionalTypeScope
  • this.visitChildren
  • this.#referencer.close
  • this.visit

Internal Comments:

// conditional types can define inferred type parameters (x6)
// which are only accessible from inside the conditional parameter (x6)
// type parameters inferred in the condition clause are not accessible within the false branch (x4)

Code
protected TSConditionalType(node: TSESTree.TSConditionalType): void {
    // conditional types can define inferred type parameters
    // which are only accessible from inside the conditional parameter
    this.#referencer.scopeManager.nestConditionalTypeScope(node);

    // type parameters inferred in the condition clause are not accessible within the false branch
    this.visitChildren(node, ['falseType']);

    this.#referencer.close(node);

    this.visit(node.falseType);
  }

TypeVisitor.TSConstructorType(node: TSESTree.TSConstructorType): void

Parameters:

  • node TSESTree.TSConstructorType

Returns: void

Calls:

  • this.visitFunctionType
Code
protected TSConstructorType(node: TSESTree.TSConstructorType): void {
    this.visitFunctionType(node);
  }

TypeVisitor.TSConstructSignatureDeclaration(node: TSESTree.TSConstructSignatureDeclaration): void

Parameters:

  • node TSESTree.TSConstructSignatureDeclaration

Returns: void

Calls:

  • this.visitFunctionType
Code
protected TSConstructSignatureDeclaration(
    node: TSESTree.TSConstructSignatureDeclaration,
  ): void {
    this.visitFunctionType(node);
  }

TypeVisitor.TSFunctionType(node: TSESTree.TSFunctionType): void

Parameters:

  • node TSESTree.TSFunctionType

Returns: void

Calls:

  • this.visitFunctionType
Code
protected TSFunctionType(node: TSESTree.TSFunctionType): void {
    this.visitFunctionType(node);
  }

TypeVisitor.TSImportType(node: TSESTree.TSImportType): void

Parameters:

  • node TSESTree.TSImportType

Returns: void

Calls:

  • this.visit

Internal Comments:

// the TS parser allows any type to be the parameter, but it's a syntax error - so we can ignore it (x4)

Code
protected TSImportType(node: TSESTree.TSImportType): void {
    // the TS parser allows any type to be the parameter, but it's a syntax error - so we can ignore it
    this.visit(node.typeArguments);
    // the qualifier is just part of a standard EntityName, so it should not be visited
  }

TypeVisitor.TSIndexSignature(node: TSESTree.TSIndexSignature): void

Parameters:

  • node TSESTree.TSIndexSignature

Returns: void

Calls:

  • this.visit
Code
protected TSIndexSignature(node: TSESTree.TSIndexSignature): void {
    for (const param of node.parameters) {
      if (param.type === AST_NODE_TYPES.Identifier) {
        this.visit(param.typeAnnotation);
      }
    }
    this.visit(node.typeAnnotation);
  }

TypeVisitor.TSInferType(node: TSESTree.TSInferType): void

Parameters:

  • node TSESTree.TSInferType

Returns: void

Calls:

  • this.#referencer.currentScope
  • scope.defineIdentifier
  • this.visit

Internal Comments:

/*
    In cases where there is a sub-type scope created within a conditional type, then the generic should be defined in the
    conditional type's scope, not the child type scope.
    If we define it within the child type's scope then it won't be able to be referenced outside the child type
    */
// search up the scope tree to figure out if we're in a nested type scope (x2)
// ensure valid type parents only (x3)

Code
protected TSInferType(node: TSESTree.TSInferType): void {
    const typeParameter = node.typeParameter;
    let scope = this.#referencer.currentScope();

    /*
    In cases where there is a sub-type scope created within a conditional type, then the generic should be defined in the
    conditional type's scope, not the child type scope.
    If we define it within the child type's scope then it won't be able to be referenced outside the child type
    */
    if (
      scope.type === ScopeType.functionType ||
      scope.type === ScopeType.mappedType
    ) {
      // search up the scope tree to figure out if we're in a nested type scope
      let currentScope = scope.upper as Scope | undefined;
      while (currentScope) {
        if (
          currentScope.type === ScopeType.functionType ||
          currentScope.type === ScopeType.mappedType
        ) {
          // ensure valid type parents only
          currentScope = currentScope.upper;
          continue;
        }
        if (currentScope.type === ScopeType.conditionalType) {
          scope = currentScope;
          break;
        }
        break;
      }
    }

    scope.defineIdentifier(
      typeParameter.name,
      new TypeDefinition(typeParameter.name, typeParameter),
    );

    this.visit(typeParameter.constraint);
  }

TypeVisitor.TSInterfaceDeclaration(node: TSESTree.TSInterfaceDeclaration): void

Parameters:

  • node TSESTree.TSInterfaceDeclaration

Returns: void

Calls:

  • this.#referencer .currentScope() .defineIdentifier
  • this.#referencer.scopeManager.nestTypeScope
  • this.visit
  • node.extends.forEach
  • this.#referencer.close

Internal Comments:

// type parameters cannot be referenced from outside their current scope (x6)

Code
protected TSInterfaceDeclaration(
    node: TSESTree.TSInterfaceDeclaration,
  ): void {
    this.#referencer
      .currentScope()
      .defineIdentifier(node.id, new TypeDefinition(node.id, node));

    if (node.typeParameters) {
      // type parameters cannot be referenced from outside their current scope
      this.#referencer.scopeManager.nestTypeScope(node);
      this.visit(node.typeParameters);
    }

    node.extends.forEach(this.visit, this);
    this.visit(node.body);

    if (node.typeParameters) {
      this.#referencer.close(node);
    }
  }

TypeVisitor.TSMappedType(node: TSESTree.TSMappedType): void

Parameters:

  • node TSESTree.TSMappedType

Returns: void

Calls:

  • this.#referencer.scopeManager.nestMappedTypeScope
  • this.#referencer .currentScope() .defineIdentifier
  • this.visit
  • this.#referencer.close

Internal Comments:

// mapped types key can only be referenced within their return value (x6)

Code
protected TSMappedType(node: TSESTree.TSMappedType): void {
    // mapped types key can only be referenced within their return value
    this.#referencer.scopeManager.nestMappedTypeScope(node);
    this.#referencer
      .currentScope()
      .defineIdentifier(node.key, new TypeDefinition(node.key, node));
    this.visit(node.constraint);
    this.visit(node.nameType);
    this.visit(node.typeAnnotation);
    this.#referencer.close(node);
  }

TypeVisitor.TSMethodSignature(node: TSESTree.TSMethodSignature): void

Parameters:

  • node TSESTree.TSMethodSignature

Returns: void

Calls:

  • this.visitPropertyKey
  • this.visitFunctionType
Code
protected TSMethodSignature(node: TSESTree.TSMethodSignature): void {
    this.visitPropertyKey(node);
    this.visitFunctionType(node);
  }

TypeVisitor.TSNamedTupleMember(node: TSESTree.TSNamedTupleMember): void

Parameters:

  • node TSESTree.TSNamedTupleMember

Returns: void

Calls:

  • this.visit
Code
protected TSNamedTupleMember(node: TSESTree.TSNamedTupleMember): void {
    this.visit(node.elementType);
    // we don't visit the label as the label only exists for the purposes of documentation
  }

TypeVisitor.TSPropertySignature(node: TSESTree.TSPropertySignature): void

Parameters:

  • node TSESTree.TSPropertySignature

Returns: void

Calls:

  • this.visitPropertyKey
  • this.visit
Code
protected TSPropertySignature(node: TSESTree.TSPropertySignature): void {
    this.visitPropertyKey(node);
    this.visit(node.typeAnnotation);
  }

TypeVisitor.TSQualifiedName(node: TSESTree.TSQualifiedName): void

Parameters:

  • node TSESTree.TSQualifiedName

Returns: void

Calls:

  • this.visit
Code
protected TSQualifiedName(node: TSESTree.TSQualifiedName): void {
    this.visit(node.left);
    // we don't visit the right as it a name on the thing, not a name to reference
  }

TypeVisitor.TSTypeAliasDeclaration(node: TSESTree.TSTypeAliasDeclaration): void

Parameters:

  • node TSESTree.TSTypeAliasDeclaration

Returns: void

Calls:

  • this.#referencer .currentScope() .defineIdentifier
  • this.#referencer.scopeManager.nestTypeScope
  • this.visit
  • this.#referencer.close

Internal Comments:

// type parameters cannot be referenced from outside their current scope (x6)

Code
protected TSTypeAliasDeclaration(
    node: TSESTree.TSTypeAliasDeclaration,
  ): void {
    this.#referencer
      .currentScope()
      .defineIdentifier(node.id, new TypeDefinition(node.id, node));

    if (node.typeParameters) {
      // type parameters cannot be referenced from outside their current scope
      this.#referencer.scopeManager.nestTypeScope(node);
      this.visit(node.typeParameters);
    }

    this.visit(node.typeAnnotation);

    if (node.typeParameters) {
      this.#referencer.close(node);
    }
  }

TypeVisitor.TSTypeParameter(node: TSESTree.TSTypeParameter): void

Parameters:

  • node TSESTree.TSTypeParameter

Returns: void

Calls:

  • this.#referencer .currentScope() .defineIdentifier
  • this.visit
Code
protected TSTypeParameter(node: TSESTree.TSTypeParameter): void {
    this.#referencer
      .currentScope()
      .defineIdentifier(node.name, new TypeDefinition(node.name, node));

    this.visit(node.constraint);
    this.visit(node.default);
  }

TypeVisitor.TSTypePredicate(node: TSESTree.TSTypePredicate): void

Parameters:

  • node TSESTree.TSTypePredicate

Returns: void

Calls:

  • this.#referencer.currentScope().referenceValue
  • this.visit
Code
protected TSTypePredicate(node: TSESTree.TSTypePredicate): void {
    if (node.parameterName.type !== AST_NODE_TYPES.TSThisType) {
      this.#referencer.currentScope().referenceValue(node.parameterName);
    }
    this.visit(node.typeAnnotation);
  }

TypeVisitor.TSTypeAnnotation(node: TSESTree.TSTypeAnnotation): void

Parameters:

  • node TSESTree.TSTypeAnnotation

Returns: void

Calls:

  • this.visitChildren

Internal Comments:

// check (x4)

Code
protected TSTypeAnnotation(node: TSESTree.TSTypeAnnotation): void {
    // check
    this.visitChildren(node);
  }

TypeVisitor.TSTypeQuery(node: TSESTree.TSTypeQuery): void

Parameters:

  • node TSESTree.TSTypeQuery

Returns: void

Calls:

  • this.visit
  • this.#referencer.currentScope().referenceValue
Code
protected TSTypeQuery(node: TSESTree.TSTypeQuery): void {
    let entityName:
      TSESTree.Identifier | TSESTree.ThisExpression | TSESTree.TSImportType;
    if (node.exprName.type === AST_NODE_TYPES.TSQualifiedName) {
      let iter = node.exprName;
      while (iter.left.type === AST_NODE_TYPES.TSQualifiedName) {
        iter = iter.left;
      }
      entityName = iter.left;
    } else {
      entityName = node.exprName;

      if (node.exprName.type === AST_NODE_TYPES.TSImportType) {
        this.visit(node.exprName);
      }
    }
    if (entityName.type === AST_NODE_TYPES.Identifier) {
      this.#referencer.currentScope().referenceValue(entityName);
    }

    this.visit(node.typeArguments);
  }

Classes

TypeVisitor

Extends: Visitor

Methods (24) — full entries under Functions

Method Signature
visit (referencer: Referencer, node: TSESTree.Node): void
visitFunctionType (node: \| TSESTree.TSCallSignatureDeclaration \| TSESTree.TSConstructorType \| TSESTree.TSConstru...
visitPropertyKey (node: TSESTree.TSMethodSignature \| TSESTree.TSPropertySignature): void
Identifier (node: TSESTree.Identifier): void
MemberExpression (node: TSESTree.MemberExpression): void
TSCallSignatureDeclaration (node: TSESTree.TSCallSignatureDeclaration): void
TSConditionalType (node: TSESTree.TSConditionalType): void
TSConstructorType (node: TSESTree.TSConstructorType): void
TSConstructSignatureDeclaration (node: TSESTree.TSConstructSignatureDeclaration): void
TSFunctionType (node: TSESTree.TSFunctionType): void
TSImportType (node: TSESTree.TSImportType): void
TSIndexSignature (node: TSESTree.TSIndexSignature): void
TSInferType (node: TSESTree.TSInferType): void
TSInterfaceDeclaration (node: TSESTree.TSInterfaceDeclaration): void
TSMappedType (node: TSESTree.TSMappedType): void
TSMethodSignature (node: TSESTree.TSMethodSignature): void
TSNamedTupleMember (node: TSESTree.TSNamedTupleMember): void
TSPropertySignature (node: TSESTree.TSPropertySignature): void
TSQualifiedName (node: TSESTree.TSQualifiedName): void
TSTypeAliasDeclaration (node: TSESTree.TSTypeAliasDeclaration): void
TSTypeParameter (node: TSESTree.TSTypeParameter): void
TSTypePredicate (node: TSESTree.TSTypePredicate): void
TSTypeAnnotation (node: TSESTree.TSTypeAnnotation): void
TSTypeQuery (node: TSESTree.TSTypeQuery): void

Generated by Syntax Scribe