Skip to content

⬅️ Back to Table of Contents

πŸ“„ typedef

πŸ“Š Analysis Summary

Metric Count
πŸ”§ Functions 7
πŸ“¦ Imports 3
πŸ“‘ Type Aliases 2
🎯 Enums 1

πŸ“š Table of Contents

πŸ› οΈ File Location:

πŸ“‚ packages/eslint-plugin/src/rules/typedef.ts

πŸ“€ Default Export

export default createRule<Options, MessageIds>({ ... })
Property Value
name 'typedef'
meta.type 'suggestion'
meta.deprecated.deprecatedSince '8.33.0'
meta.deprecated.message 'This is an old rule that is no longer recommended for use.'
meta.docs.description 'Require type annotations in certain places'
meta.messages.expectedTypedef 'Expected a type annotation.'
meta.messages.expectedTypedefNamed 'Expected {{name}} to have a type annotation.'
meta.schema [ { type: 'object', additionalProperties: false, properties: { [OptionKeys.ArrayDestructuring]: { type: 'boolean', de...
defaultOptions [ { [OptionKeys.ArrayDestructuring]: false, [OptionKeys.ArrowParameter]: false, [OptionKeys.MemberVariableDeclaration...

Entry point: create β€” documented under Functions.


πŸ“¦ Imports

Name Source
TSESTree @typescript-eslint/utils
AST_NODE_TYPES @typescript-eslint/utils
createRule ../util

Functions

create(context: any, [ { arrayDestructuring, arrowPa…: any): { VariableDeclarator(node: any): void; 'TSIndexSignature, T…

Parameters:

  • context any
  • [ { arrayDestructuring, arrowParameter, memberVariableDeclaration, objectDestructuring, parameter, propertyDeclaration, variableDeclaration, variableDeclarationIgnoreFunction, }, ] any

Returns: { VariableDeclarator(node: any): void; 'TSIndexSignature, TSPropertySignature'(node: TSESTree.TSIndexSignature | TSESTree.TSPropertySignature): void; ObjectPattern(node: any): void; 'FunctionDeclaration, FunctionExpression'(node: TSESTree.FunctionDeclaration | TSESTree.FunctionExpression): void; PropertyDefinition(node: any): void; ArrowFunctionExpression(node: any): void; ArrayPattern(node: any): void; }

Calls:

  • context.report
  • report
  • getNodeName
  • isForOfStatementContext
  • isAncestorHasTypeAnnotation
  • checkParameters
  • isVariableDeclarationIgnoreFunction

Internal Comments:

// Check TS parameter property with default value like `constructor(private param: string = 'something') {}`
// Keep looking upwards (x3)
// Stop traversing and don't report an error
// Stop traversing (x3)

Code
create(
    context,
    [
      {
        arrayDestructuring,
        arrowParameter,
        memberVariableDeclaration,
        objectDestructuring,
        parameter,
        propertyDeclaration,
        variableDeclaration,
        variableDeclarationIgnoreFunction,
      },
    ],
  ) {
    function report(location: TSESTree.Node, name?: string): void {
      context.report({
        node: location,
        messageId: name ? 'expectedTypedefNamed' : 'expectedTypedef',
        data: { name },
      });
    }

    function getNodeName(
      node: TSESTree.Parameter | TSESTree.PropertyName,
    ): string | undefined {
      return node.type === AST_NODE_TYPES.Identifier ? node.name : undefined;
    }

    function isForOfStatementContext(
      node: TSESTree.ArrayPattern | TSESTree.ObjectPattern,
    ): boolean {
      let current: TSESTree.Node | undefined = node.parent;
      while (current) {
        switch (current.type) {
          case AST_NODE_TYPES.VariableDeclarator:
          case AST_NODE_TYPES.VariableDeclaration:
          case AST_NODE_TYPES.ObjectPattern:
          case AST_NODE_TYPES.ArrayPattern:
          case AST_NODE_TYPES.Property:
            current = current.parent;
            break;

          case AST_NODE_TYPES.ForOfStatement:
            return true;

          default:
            current = undefined;
        }
      }

      return false;
    }

    function checkParameters(params: TSESTree.Parameter[]): void {
      for (const param of params) {
        let annotationNode: TSESTree.Node | undefined;

        switch (param.type) {
          case AST_NODE_TYPES.AssignmentPattern:
            annotationNode = param.left;
            break;
          case AST_NODE_TYPES.TSParameterProperty:
            annotationNode = param.parameter;

            // Check TS parameter property with default value like `constructor(private param: string = 'something') {}`
            if (annotationNode.type === AST_NODE_TYPES.AssignmentPattern) {
              annotationNode = annotationNode.left;
            }

            break;
          default:
            annotationNode = param;
            break;
        }

        if (!annotationNode.typeAnnotation) {
          report(param, getNodeName(param));
        }
      }
    }

    function isVariableDeclarationIgnoreFunction(node: TSESTree.Node): boolean {
      return (
        variableDeclarationIgnoreFunction === true &&
        (node.type === AST_NODE_TYPES.ArrowFunctionExpression ||
          node.type === AST_NODE_TYPES.FunctionExpression)
      );
    }

    function isAncestorHasTypeAnnotation(
      node: TSESTree.ArrayPattern | TSESTree.ObjectPattern,
    ): boolean {
      let ancestor: TSESTree.Node | undefined = node.parent;

      while (ancestor) {
        if (
          (ancestor.type === AST_NODE_TYPES.ObjectPattern ||
            ancestor.type === AST_NODE_TYPES.ArrayPattern) &&
          ancestor.typeAnnotation
        ) {
          return true;
        }

        ancestor = ancestor.parent;
      }

      return false;
    }

    return {
      ...(arrayDestructuring && {
        ArrayPattern(node): void {
          if (
            node.parent.type === AST_NODE_TYPES.RestElement &&
            node.parent.typeAnnotation
          ) {
            return;
          }

          if (
            !node.typeAnnotation &&
            !isForOfStatementContext(node) &&
            !isAncestorHasTypeAnnotation(node) &&
            node.parent.type !== AST_NODE_TYPES.AssignmentExpression
          ) {
            report(node);
          }
        },
      }),
      ...(arrowParameter && {
        ArrowFunctionExpression(node): void {
          checkParameters(node.params);
        },
      }),
      ...(memberVariableDeclaration && {
        PropertyDefinition(node): void {
          if (
            !(node.value && isVariableDeclarationIgnoreFunction(node.value)) &&
            !node.typeAnnotation
          ) {
            report(
              node,
              node.key.type === AST_NODE_TYPES.Identifier
                ? node.key.name
                : undefined,
            );
          }
        },
      }),
      ...(parameter && {
        'FunctionDeclaration, FunctionExpression'(
          node: TSESTree.FunctionDeclaration | TSESTree.FunctionExpression,
        ): void {
          checkParameters(node.params);
        },
      }),
      ...(objectDestructuring && {
        ObjectPattern(node): void {
          if (
            !node.typeAnnotation &&
            !isForOfStatementContext(node) &&
            !isAncestorHasTypeAnnotation(node)
          ) {
            report(node);
          }
        },
      }),
      ...(propertyDeclaration && {
        'TSIndexSignature, TSPropertySignature'(
          node: TSESTree.TSIndexSignature | TSESTree.TSPropertySignature,
        ): void {
          if (!node.typeAnnotation) {
            report(
              node,
              node.type === AST_NODE_TYPES.TSPropertySignature
                ? getNodeName(node.key)
                : undefined,
            );
          }
        },
      }),
      VariableDeclarator(node): void {
        if (
          !variableDeclaration ||
          node.id.typeAnnotation ||
          (node.id.type === AST_NODE_TYPES.ArrayPattern &&
            !arrayDestructuring) ||
          (node.id.type === AST_NODE_TYPES.ObjectPattern &&
            !objectDestructuring) ||
          (node.init && isVariableDeclarationIgnoreFunction(node.init))
        ) {
          return;
        }

        let current: TSESTree.Node | undefined = node.parent;
        while (current) {
          switch (current.type) {
            case AST_NODE_TYPES.VariableDeclaration:
              // Keep looking upwards
              current = current.parent;
              break;
            case AST_NODE_TYPES.ForOfStatement:
            case AST_NODE_TYPES.ForInStatement:
              // Stop traversing and don't report an error
              return;
            default:
              // Stop traversing
              current = undefined;
              break;
          }
        }

        report(node, getNodeName(node.id));
      },
    };
  }

Internal helpers

Declared inside another function in this file.

report(location: TSESTree.Node, name: string): void

Parameters:

  • location TSESTree.Node
  • name string

Returns: void

Calls:

  • context.report
Code
function report(location: TSESTree.Node, name?: string): void {
      context.report({
        node: location,
        messageId: name ? 'expectedTypedefNamed' : 'expectedTypedef',
        data: { name },
      });
    }

getNodeName(node: TSESTree.Parameter | TSESTree.PropertyN…): string | undefined

Parameters:

  • node TSESTree.Parameter | TSESTree.PropertyName

Returns: string | undefined

Code
function getNodeName(
      node: TSESTree.Parameter | TSESTree.PropertyName,
    ): string | undefined {
      return node.type === AST_NODE_TYPES.Identifier ? node.name : undefined;
    }

isForOfStatementContext(node: TSESTree.ArrayPattern | TSESTree.Object…): boolean

Parameters:

  • node TSESTree.ArrayPattern | TSESTree.ObjectPattern

Returns: boolean

Code
function isForOfStatementContext(
      node: TSESTree.ArrayPattern | TSESTree.ObjectPattern,
    ): boolean {
      let current: TSESTree.Node | undefined = node.parent;
      while (current) {
        switch (current.type) {
          case AST_NODE_TYPES.VariableDeclarator:
          case AST_NODE_TYPES.VariableDeclaration:
          case AST_NODE_TYPES.ObjectPattern:
          case AST_NODE_TYPES.ArrayPattern:
          case AST_NODE_TYPES.Property:
            current = current.parent;
            break;

          case AST_NODE_TYPES.ForOfStatement:
            return true;

          default:
            current = undefined;
        }
      }

      return false;
    }

checkParameters(params: TSESTree.Parameter[]): void

Parameters:

  • params TSESTree.Parameter[]

Returns: void

Calls:

  • report
  • getNodeName

Internal Comments:

// Check TS parameter property with default value like `constructor(private param: string = 'something') {}`

Code
function checkParameters(params: TSESTree.Parameter[]): void {
      for (const param of params) {
        let annotationNode: TSESTree.Node | undefined;

        switch (param.type) {
          case AST_NODE_TYPES.AssignmentPattern:
            annotationNode = param.left;
            break;
          case AST_NODE_TYPES.TSParameterProperty:
            annotationNode = param.parameter;

            // Check TS parameter property with default value like `constructor(private param: string = 'something') {}`
            if (annotationNode.type === AST_NODE_TYPES.AssignmentPattern) {
              annotationNode = annotationNode.left;
            }

            break;
          default:
            annotationNode = param;
            break;
        }

        if (!annotationNode.typeAnnotation) {
          report(param, getNodeName(param));
        }
      }
    }

isVariableDeclarationIgnoreFunction(node: TSESTree.Node): boolean

Parameters:

  • node TSESTree.Node

Returns: boolean

Code
function isVariableDeclarationIgnoreFunction(node: TSESTree.Node): boolean {
      return (
        variableDeclarationIgnoreFunction === true &&
        (node.type === AST_NODE_TYPES.ArrowFunctionExpression ||
          node.type === AST_NODE_TYPES.FunctionExpression)
      );
    }

isAncestorHasTypeAnnotation(node: TSESTree.ArrayPattern | TSESTree.Object…): boolean

Parameters:

  • node TSESTree.ArrayPattern | TSESTree.ObjectPattern

Returns: boolean

Code
function isAncestorHasTypeAnnotation(
      node: TSESTree.ArrayPattern | TSESTree.ObjectPattern,
    ): boolean {
      let ancestor: TSESTree.Node | undefined = node.parent;

      while (ancestor) {
        if (
          (ancestor.type === AST_NODE_TYPES.ObjectPattern ||
            ancestor.type === AST_NODE_TYPES.ArrayPattern) &&
          ancestor.typeAnnotation
        ) {
          return true;
        }

        ancestor = ancestor.parent;
      }

      return false;
    }

Type Aliases

Options

type Options = [Partial<Record<OptionKeys, boolean>>];

MessageIds

type MessageIds = 'expectedTypedef' | 'expectedTypedefNamed';

Enums

const enum OptionKeys

Enum Code
export const enum OptionKeys {
  ArrayDestructuring = 'arrayDestructuring',
  ArrowParameter = 'arrowParameter',
  MemberVariableDeclaration = 'memberVariableDeclaration',
  ObjectDestructuring = 'objectDestructuring',
  Parameter = 'parameter',
  PropertyDeclaration = 'propertyDeclaration',
  VariableDeclaration = 'variableDeclaration',
  VariableDeclarationIgnoreFunction = 'variableDeclarationIgnoreFunction',
}

Members

Name Value Description
ArrayDestructuring arrayDestructuring not shown
ArrowParameter arrowParameter not shown
MemberVariableDeclaration memberVariableDeclaration not shown
ObjectDestructuring objectDestructuring not shown
Parameter parameter not shown
PropertyDeclaration propertyDeclaration not shown
VariableDeclaration variableDeclaration not shown
VariableDeclarationIgnoreFunction variableDeclarationIgnoreFunction not shown

Generated by Syntax Scribe