Skip to content

⬅️ Back to Table of Contents

πŸ“„ no-useless-default-assignment

πŸ“Š Analysis Summary

Metric Count
πŸ”§ Functions 13
πŸ“¦ Imports 12
πŸ“‘ Type Aliases 2

πŸ“š Table of Contents

πŸ› οΈ File Location:

πŸ“‚ packages/eslint-plugin/src/rules/no-useless-default-assignment.ts

πŸ“€ Default Export

export default createRule<Options, MessageId>({ ... })
Property Value
name 'no-useless-default-assignment'
meta.type 'suggestion'
meta.docs.description 'Disallow default values that will never be used'
meta.docs.recommended 'strict'
meta.docs.requiresTypeChecking true
meta.fixable 'code'
meta.messages.noStrictNullCheck 'This rule requires the strictNullChecks compiler option to be turned on to function correctly.'
meta.messages.preferOptionalSyntax 'Using = undefined to make a parameter optional adds unnecessary runtime logic. Use the ? optional syntax instead.'
meta.messages.uselessDefaultAssignment 'Default value is useless because the {{ type }} is not optional.'
meta.messages.uselessUndefined 'Default value is useless because it is undefined. Optional {{ type }}s are already undefined by default.'
meta.schema [ { type: 'object', additionalProperties: false, properties: { allowRuleToRunWithoutStrictNullChecksIKnowWhatIAmDoing...
defaultOptions [ { allowRuleToRunWithoutStrictNullChecksIKnowWhatIAmDoing: false, }, ]

Entry point: create β€” documented under Functions.


πŸ“¦ Imports

Name Source
TSESLint @typescript-eslint/utils
TSESTree @typescript-eslint/utils
AST_NODE_TYPES @typescript-eslint/utils
createRule ../util
getParserServices ../util
isFunction ../util
isRestParameterDeclaration ../util
isTypeAnyType ../util
isTypeFlagSet ../util
isTypeUnknownType ../util
nullThrows ../util
NullThrowsReasons ../util

Functions

create(context: any, [{ allowRuleToRunWithoutStrictN…: any): { AssignmentPattern: (node: TSESTree.AssignmentPattern) => …

Parameters:

  • context any
  • [{ allowRuleToRunWithoutStrictNullChecksIKnowWhatIAmDoing }] any

Returns: { AssignmentPattern: (node: TSESTree.AssignmentPattern) => void; }

Calls:

  • getParserServices (from ../util)
  • services.program.getTypeChecker
  • services.program.getCompilerOptions
  • tsutils.isStrictCompilerOptionEnabled
  • context.report
  • isTypeAnyType (from ../util)
  • isTypeUnknownType (from ../util)
  • tsutils .unionConstituents(type) .some
  • isTypeFlagSet (from ../util)
  • checker.isTupleType
  • checker.getTypeArguments
  • arrayType.getNumberIndexType
  • services.esTreeNodeToTSNodeMap.get
  • ts.isParameter
  • canBeUndefined
  • checker.getTypeFromTypeNode
  • reportPreferOptionalSyntax
  • reportUselessUndefined
  • parent.params.indexOf
  • ts.isFunctionLike
  • checker.getContextualType
  • contextualType.getCallSignatures
  • signatures[0].getDeclaration
  • signatures.some
  • signature.getParameters
  • isRestParameterDeclaration (from ../util)
  • tsutils.isSymbolFlagSet
  • checker.getTypeOfSymbol
  • tsutils.isTypeParameter
  • reportUselessDefaultAssignment
  • getTypeOfProperty
  • getSourceTypeForPattern
  • parent.elements.indexOf
  • getPropertyName
  • sourceType.getProperty
  • hasConditionalInitializer
  • hasPropertyInAllBranches
  • nullThrows (from ../util)
  • checker.getTypeAtLocation
  • isFunction (from ../util)
  • checker.getSignatureFromDeclaration
  • NullThrowsReasons.MissingToken
  • getArrayElementType
  • String
  • removeDefault
  • fixer.insertTextAfterRange
  • fixer.removeRange
  • expression.properties.some

Internal Comments:

// tsFunc is already a FunctionLike subtype; defensive runtime check
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition

Code
create(
    context,
    [{ allowRuleToRunWithoutStrictNullChecksIKnowWhatIAmDoing }],
  ) {
    const services = getParserServices(context);
    const checker = services.program.getTypeChecker();

    const compilerOptions = services.program.getCompilerOptions();
    const isStrictNullChecks = tsutils.isStrictCompilerOptionEnabled(
      compilerOptions,
      'strictNullChecks',
    );

    if (
      !isStrictNullChecks &&
      allowRuleToRunWithoutStrictNullChecksIKnowWhatIAmDoing !== true
    ) {
      context.report({
        loc: {
          start: { column: 0, line: 0 },
          end: { column: 0, line: 0 },
        },
        messageId: 'noStrictNullCheck',
      });
    }

    function canBeUndefined(type: ts.Type): boolean {
      if (isTypeAnyType(type) || isTypeUnknownType(type)) {
        return true;
      }
      return tsutils
        .unionConstituents(type)
        .some(part => isTypeFlagSet(part, ts.TypeFlags.Undefined));
    }

    function getArrayElementType(
      arrayType: ts.Type,
      elementIndex: number,
    ): ts.Type | null {
      if (checker.isTupleType(arrayType)) {
        const tupleArgs = checker.getTypeArguments(arrayType);
        if (elementIndex < tupleArgs.length) {
          return tupleArgs[elementIndex];
        }
      }

      return arrayType.getNumberIndexType() ?? null;
    }

    function checkAssignmentPattern(node: TSESTree.AssignmentPattern): void {
      if (
        node.right.type === AST_NODE_TYPES.Identifier &&
        node.right.name === 'undefined'
      ) {
        const tsNode = services.esTreeNodeToTSNodeMap.get(node);
        if (
          ts.isParameter(tsNode) &&
          tsNode.type &&
          canBeUndefined(checker.getTypeFromTypeNode(tsNode.type))
        ) {
          reportPreferOptionalSyntax(node);
          return;
        }

        const type =
          node.parent.type === AST_NODE_TYPES.Property ||
          node.parent.type === AST_NODE_TYPES.ArrayPattern
            ? 'property'
            : 'parameter';
        reportUselessUndefined(node, type);
        return;
      }

      const parent = node.parent;

      if (
        parent.type === AST_NODE_TYPES.ArrowFunctionExpression ||
        parent.type === AST_NODE_TYPES.FunctionExpression
      ) {
        const paramIndex = parent.params.indexOf(node);
        if (paramIndex !== -1) {
          const tsFunc = services.esTreeNodeToTSNodeMap.get(parent);
          // tsFunc is already a FunctionLike subtype; defensive runtime check
          // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
          if (ts.isFunctionLike(tsFunc)) {
            const contextualType = checker.getContextualType(
              tsFunc as ts.Expression,
            );
            if (!contextualType) {
              return;
            }

            const signatures = contextualType.getCallSignatures();
            if (
              signatures.length === 0 ||
              signatures[0].getDeclaration() === tsFunc
            ) {
              return;
            }

            const defaultCanBeUsed = signatures.some(signature => {
              const params = signature.getParameters();
              if (paramIndex >= params.length) {
                return true;
              }

              const paramSymbol = params[paramIndex];
              if (
                paramSymbol.valueDeclaration &&
                isRestParameterDeclaration(paramSymbol.valueDeclaration)
              ) {
                return true;
              }

              if (
                tsutils.isSymbolFlagSet(paramSymbol, ts.SymbolFlags.Optional)
              ) {
                return true;
              }

              const paramType = checker.getTypeOfSymbol(paramSymbol);
              return (
                tsutils.isTypeParameter(paramType) || canBeUndefined(paramType)
              );
            });

            if (!defaultCanBeUsed) {
              reportUselessDefaultAssignment(node, 'parameter');
            }
          }
        }
        return;
      }

      if (parent.type === AST_NODE_TYPES.Property) {
        const propertyType = getTypeOfProperty(parent);
        if (!propertyType) {
          return;
        }

        if (!canBeUndefined(propertyType)) {
          reportUselessDefaultAssignment(node, 'property');
        }
      } else if (parent.type === AST_NODE_TYPES.ArrayPattern) {
        const sourceType = getSourceTypeForPattern(parent);
        if (!sourceType) {
          return;
        }

        if (!checker.isTupleType(sourceType)) {
          return;
        }

        const tupleArgs = checker.getTypeArguments(sourceType);
        const elementIndex = parent.elements.indexOf(node);
        if (elementIndex < 0 || elementIndex >= tupleArgs.length) {
          return;
        }
        const elementType = tupleArgs[elementIndex];
        if (!canBeUndefined(elementType)) {
          reportUselessDefaultAssignment(node, 'property');
        }
      }
    }

    function getTypeOfProperty(node: TSESTree.Property): ts.Type | null {
      const objectPattern = node.parent as TSESTree.ObjectPattern;
      const sourceType = getSourceTypeForPattern(objectPattern);
      if (!sourceType) {
        return null;
      }

      const propertyName = getPropertyName(node.key);
      if (!propertyName) {
        return null;
      }

      const symbol = sourceType.getProperty(propertyName);
      if (!symbol) {
        return null;
      }

      if (tsutils.isSymbolFlagSet(symbol, ts.SymbolFlags.Optional)) {
        const parent = objectPattern.parent;
        if (
          parent.type === AST_NODE_TYPES.VariableDeclarator &&
          parent.init &&
          hasConditionalInitializer(objectPattern)
        ) {
          const propertyName = getPropertyName(node.key);

          if (
            !propertyName ||
            !hasPropertyInAllBranches(parent.init, propertyName)
          ) {
            return null;
          }
        }
      }

      return checker.getTypeOfSymbol(symbol);
    }

    function hasConditionalInitializer(node: TSESTree.Node): boolean {
      const parent = node.parent;
      if (!parent) {
        return false;
      }
      if (parent.type === AST_NODE_TYPES.VariableDeclarator && parent.init) {
        return (
          parent.init.type === AST_NODE_TYPES.ConditionalExpression ||
          parent.init.type === AST_NODE_TYPES.LogicalExpression
        );
      }
      return hasConditionalInitializer(parent);
    }

    function getSourceTypeForPattern(pattern: TSESTree.Node): ts.Type | null {
      const parent = nullThrows(
        pattern.parent,
        NullThrowsReasons.MissingParent,
      );

      if (parent.type === AST_NODE_TYPES.VariableDeclarator && parent.init) {
        const tsNode = services.esTreeNodeToTSNodeMap.get(parent.init);
        return checker.getTypeAtLocation(tsNode);
      }

      if (isFunction(parent)) {
        let paramIndex = parent.params.indexOf(pattern as TSESTree.Parameter);
        const tsFunc = services.esTreeNodeToTSNodeMap.get(parent);
        const signature = nullThrows(
          checker.getSignatureFromDeclaration(tsFunc),
          NullThrowsReasons.MissingToken('signature', 'function'),
        );
        const params = signature.getParameters();
        if (signature.thisParameter) {
          paramIndex--;
        }
        if (paramIndex < 0 || paramIndex >= params.length) {
          return null;
        }
        return checker.getTypeOfSymbol(params[paramIndex]);
      }

      if (parent.type === AST_NODE_TYPES.AssignmentPattern) {
        return getSourceTypeForPattern(parent);
      }

      if (parent.type === AST_NODE_TYPES.Property) {
        return getTypeOfProperty(parent);
      }

      if (parent.type === AST_NODE_TYPES.ArrayPattern) {
        const arrayType = getSourceTypeForPattern(parent);
        if (!arrayType) {
          return null;
        }
        const elementIndex = parent.elements.indexOf(
          pattern as TSESTree.DestructuringPattern,
        );
        return getArrayElementType(arrayType, elementIndex);
      }

      return null;
    }

    function getPropertyName(
      key: TSESTree.Expression | TSESTree.PrivateIdentifier,
    ): string | null {
      switch (key.type) {
        case AST_NODE_TYPES.Identifier:
          return key.name;
        case AST_NODE_TYPES.Literal:
          return String(key.value);
        case AST_NODE_TYPES.TemplateLiteral:
          return key.expressions.length ? null : key.quasis[0].value.cooked;
        default:
          return null;
      }
    }

    function reportUselessDefaultAssignment(
      node: TSESTree.AssignmentPattern,
      type: 'parameter' | 'property',
    ): void {
      context.report({
        node: node.right,
        messageId: 'uselessDefaultAssignment',
        data: { type },
        fix: fixer => removeDefault(fixer, node),
      });
    }

    function reportUselessUndefined(
      node: TSESTree.AssignmentPattern,
      type: 'parameter' | 'property',
    ): void {
      context.report({
        node: node.right,
        messageId: 'uselessUndefined',
        data: { type },
        fix: fixer => removeDefault(fixer, node),
      });
    }

    function reportPreferOptionalSyntax(
      node: TSESTree.AssignmentPattern,
    ): void {
      context.report({
        node: node.right,
        messageId: 'preferOptionalSyntax',
        *fix(fixer) {
          yield removeDefault(fixer, node);

          const { left } = node;
          if (left.type === AST_NODE_TYPES.Identifier) {
            yield fixer.insertTextAfterRange(
              [left.range[0], left.range[0] + left.name.length],
              '?',
            );
          }
        },
      });
    }

    function removeDefault(
      fixer: TSESLint.RuleFixer,
      node: TSESTree.AssignmentPattern,
    ): TSESLint.RuleFix {
      const start = node.left.range[1];
      const end = node.range[1];
      return fixer.removeRange([start, end]);
    }

    function hasPropertyInAllBranches(
      expression: TSESTree.Expression,
      propertyName: string,
    ): boolean {
      return (
        (expression.type === AST_NODE_TYPES.ObjectExpression &&
          expression.properties.some(
            prop =>
              prop.type === AST_NODE_TYPES.Property &&
              getPropertyName(prop.key) === propertyName,
          )) ||
        (expression.type === AST_NODE_TYPES.ConditionalExpression &&
          hasPropertyInAllBranches(expression.consequent, propertyName) &&
          hasPropertyInAllBranches(expression.alternate, propertyName))
      );
    }

    return {
      AssignmentPattern: checkAssignmentPattern,
    };
  }

Internal helpers

Declared inside another function in this file.

canBeUndefined(type: ts.Type): boolean

Parameters:

  • type ts.Type

Returns: boolean

Calls:

  • isTypeAnyType (from ../util)
  • isTypeUnknownType (from ../util)
  • tsutils .unionConstituents(type) .some
  • isTypeFlagSet (from ../util)
Code
function canBeUndefined(type: ts.Type): boolean {
      if (isTypeAnyType(type) || isTypeUnknownType(type)) {
        return true;
      }
      return tsutils
        .unionConstituents(type)
        .some(part => isTypeFlagSet(part, ts.TypeFlags.Undefined));
    }

getArrayElementType(arrayType: ts.Type, elementIndex: number): ts.Type | null

Parameters:

  • arrayType ts.Type
  • elementIndex number

Returns: ts.Type | null

Calls:

  • checker.isTupleType
  • checker.getTypeArguments
  • arrayType.getNumberIndexType
Code
function getArrayElementType(
      arrayType: ts.Type,
      elementIndex: number,
    ): ts.Type | null {
      if (checker.isTupleType(arrayType)) {
        const tupleArgs = checker.getTypeArguments(arrayType);
        if (elementIndex < tupleArgs.length) {
          return tupleArgs[elementIndex];
        }
      }

      return arrayType.getNumberIndexType() ?? null;
    }

checkAssignmentPattern(node: TSESTree.AssignmentPattern): void

Parameters:

  • node TSESTree.AssignmentPattern

Returns: void

Calls:

  • services.esTreeNodeToTSNodeMap.get
  • ts.isParameter
  • canBeUndefined
  • checker.getTypeFromTypeNode
  • reportPreferOptionalSyntax
  • reportUselessUndefined
  • parent.params.indexOf
  • ts.isFunctionLike
  • checker.getContextualType
  • contextualType.getCallSignatures
  • signatures[0].getDeclaration
  • signatures.some
  • signature.getParameters
  • isRestParameterDeclaration (from ../util)
  • tsutils.isSymbolFlagSet
  • checker.getTypeOfSymbol
  • tsutils.isTypeParameter
  • reportUselessDefaultAssignment
  • getTypeOfProperty
  • getSourceTypeForPattern
  • checker.isTupleType
  • checker.getTypeArguments
  • parent.elements.indexOf

Internal Comments:

// tsFunc is already a FunctionLike subtype; defensive runtime check
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition

Code
function checkAssignmentPattern(node: TSESTree.AssignmentPattern): void {
      if (
        node.right.type === AST_NODE_TYPES.Identifier &&
        node.right.name === 'undefined'
      ) {
        const tsNode = services.esTreeNodeToTSNodeMap.get(node);
        if (
          ts.isParameter(tsNode) &&
          tsNode.type &&
          canBeUndefined(checker.getTypeFromTypeNode(tsNode.type))
        ) {
          reportPreferOptionalSyntax(node);
          return;
        }

        const type =
          node.parent.type === AST_NODE_TYPES.Property ||
          node.parent.type === AST_NODE_TYPES.ArrayPattern
            ? 'property'
            : 'parameter';
        reportUselessUndefined(node, type);
        return;
      }

      const parent = node.parent;

      if (
        parent.type === AST_NODE_TYPES.ArrowFunctionExpression ||
        parent.type === AST_NODE_TYPES.FunctionExpression
      ) {
        const paramIndex = parent.params.indexOf(node);
        if (paramIndex !== -1) {
          const tsFunc = services.esTreeNodeToTSNodeMap.get(parent);
          // tsFunc is already a FunctionLike subtype; defensive runtime check
          // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
          if (ts.isFunctionLike(tsFunc)) {
            const contextualType = checker.getContextualType(
              tsFunc as ts.Expression,
            );
            if (!contextualType) {
              return;
            }

            const signatures = contextualType.getCallSignatures();
            if (
              signatures.length === 0 ||
              signatures[0].getDeclaration() === tsFunc
            ) {
              return;
            }

            const defaultCanBeUsed = signatures.some(signature => {
              const params = signature.getParameters();
              if (paramIndex >= params.length) {
                return true;
              }

              const paramSymbol = params[paramIndex];
              if (
                paramSymbol.valueDeclaration &&
                isRestParameterDeclaration(paramSymbol.valueDeclaration)
              ) {
                return true;
              }

              if (
                tsutils.isSymbolFlagSet(paramSymbol, ts.SymbolFlags.Optional)
              ) {
                return true;
              }

              const paramType = checker.getTypeOfSymbol(paramSymbol);
              return (
                tsutils.isTypeParameter(paramType) || canBeUndefined(paramType)
              );
            });

            if (!defaultCanBeUsed) {
              reportUselessDefaultAssignment(node, 'parameter');
            }
          }
        }
        return;
      }

      if (parent.type === AST_NODE_TYPES.Property) {
        const propertyType = getTypeOfProperty(parent);
        if (!propertyType) {
          return;
        }

        if (!canBeUndefined(propertyType)) {
          reportUselessDefaultAssignment(node, 'property');
        }
      } else if (parent.type === AST_NODE_TYPES.ArrayPattern) {
        const sourceType = getSourceTypeForPattern(parent);
        if (!sourceType) {
          return;
        }

        if (!checker.isTupleType(sourceType)) {
          return;
        }

        const tupleArgs = checker.getTypeArguments(sourceType);
        const elementIndex = parent.elements.indexOf(node);
        if (elementIndex < 0 || elementIndex >= tupleArgs.length) {
          return;
        }
        const elementType = tupleArgs[elementIndex];
        if (!canBeUndefined(elementType)) {
          reportUselessDefaultAssignment(node, 'property');
        }
      }
    }

getTypeOfProperty(node: TSESTree.Property): ts.Type | null

Parameters:

  • node TSESTree.Property

Returns: ts.Type | null

Calls:

  • getSourceTypeForPattern
  • getPropertyName
  • sourceType.getProperty
  • tsutils.isSymbolFlagSet
  • hasConditionalInitializer
  • hasPropertyInAllBranches
  • checker.getTypeOfSymbol
Code
function getTypeOfProperty(node: TSESTree.Property): ts.Type | null {
      const objectPattern = node.parent as TSESTree.ObjectPattern;
      const sourceType = getSourceTypeForPattern(objectPattern);
      if (!sourceType) {
        return null;
      }

      const propertyName = getPropertyName(node.key);
      if (!propertyName) {
        return null;
      }

      const symbol = sourceType.getProperty(propertyName);
      if (!symbol) {
        return null;
      }

      if (tsutils.isSymbolFlagSet(symbol, ts.SymbolFlags.Optional)) {
        const parent = objectPattern.parent;
        if (
          parent.type === AST_NODE_TYPES.VariableDeclarator &&
          parent.init &&
          hasConditionalInitializer(objectPattern)
        ) {
          const propertyName = getPropertyName(node.key);

          if (
            !propertyName ||
            !hasPropertyInAllBranches(parent.init, propertyName)
          ) {
            return null;
          }
        }
      }

      return checker.getTypeOfSymbol(symbol);
    }

hasConditionalInitializer(node: TSESTree.Node): boolean

Parameters:

  • node TSESTree.Node

Returns: boolean

Calls:

  • hasConditionalInitializer
Code
function hasConditionalInitializer(node: TSESTree.Node): boolean {
      const parent = node.parent;
      if (!parent) {
        return false;
      }
      if (parent.type === AST_NODE_TYPES.VariableDeclarator && parent.init) {
        return (
          parent.init.type === AST_NODE_TYPES.ConditionalExpression ||
          parent.init.type === AST_NODE_TYPES.LogicalExpression
        );
      }
      return hasConditionalInitializer(parent);
    }

getSourceTypeForPattern(pattern: TSESTree.Node): ts.Type | null

Parameters:

  • pattern TSESTree.Node

Returns: ts.Type | null

Calls:

  • nullThrows (from ../util)
  • services.esTreeNodeToTSNodeMap.get
  • checker.getTypeAtLocation
  • isFunction (from ../util)
  • parent.params.indexOf
  • checker.getSignatureFromDeclaration
  • NullThrowsReasons.MissingToken
  • signature.getParameters
  • checker.getTypeOfSymbol
  • getSourceTypeForPattern
  • getTypeOfProperty
  • parent.elements.indexOf
  • getArrayElementType
Code
function getSourceTypeForPattern(pattern: TSESTree.Node): ts.Type | null {
      const parent = nullThrows(
        pattern.parent,
        NullThrowsReasons.MissingParent,
      );

      if (parent.type === AST_NODE_TYPES.VariableDeclarator && parent.init) {
        const tsNode = services.esTreeNodeToTSNodeMap.get(parent.init);
        return checker.getTypeAtLocation(tsNode);
      }

      if (isFunction(parent)) {
        let paramIndex = parent.params.indexOf(pattern as TSESTree.Parameter);
        const tsFunc = services.esTreeNodeToTSNodeMap.get(parent);
        const signature = nullThrows(
          checker.getSignatureFromDeclaration(tsFunc),
          NullThrowsReasons.MissingToken('signature', 'function'),
        );
        const params = signature.getParameters();
        if (signature.thisParameter) {
          paramIndex--;
        }
        if (paramIndex < 0 || paramIndex >= params.length) {
          return null;
        }
        return checker.getTypeOfSymbol(params[paramIndex]);
      }

      if (parent.type === AST_NODE_TYPES.AssignmentPattern) {
        return getSourceTypeForPattern(parent);
      }

      if (parent.type === AST_NODE_TYPES.Property) {
        return getTypeOfProperty(parent);
      }

      if (parent.type === AST_NODE_TYPES.ArrayPattern) {
        const arrayType = getSourceTypeForPattern(parent);
        if (!arrayType) {
          return null;
        }
        const elementIndex = parent.elements.indexOf(
          pattern as TSESTree.DestructuringPattern,
        );
        return getArrayElementType(arrayType, elementIndex);
      }

      return null;
    }

getPropertyName(key: TSESTree.Expression | TSESTree.PrivateI…): string | null

Parameters:

  • key TSESTree.Expression | TSESTree.PrivateIdentifier

Returns: string | null

Calls:

  • String
Code
function getPropertyName(
      key: TSESTree.Expression | TSESTree.PrivateIdentifier,
    ): string | null {
      switch (key.type) {
        case AST_NODE_TYPES.Identifier:
          return key.name;
        case AST_NODE_TYPES.Literal:
          return String(key.value);
        case AST_NODE_TYPES.TemplateLiteral:
          return key.expressions.length ? null : key.quasis[0].value.cooked;
        default:
          return null;
      }
    }

reportUselessDefaultAssignment(node: TSESTree.AssignmentPattern, type: 'parameter' | 'property'): void

Parameters:

  • node TSESTree.AssignmentPattern
  • type 'parameter' | 'property'

Returns: void

Calls:

  • context.report
  • removeDefault
Code
function reportUselessDefaultAssignment(
      node: TSESTree.AssignmentPattern,
      type: 'parameter' | 'property',
    ): void {
      context.report({
        node: node.right,
        messageId: 'uselessDefaultAssignment',
        data: { type },
        fix: fixer => removeDefault(fixer, node),
      });
    }

reportUselessUndefined(node: TSESTree.AssignmentPattern, type: 'parameter' | 'property'): void

Parameters:

  • node TSESTree.AssignmentPattern
  • type 'parameter' | 'property'

Returns: void

Calls:

  • context.report
  • removeDefault
Code
function reportUselessUndefined(
      node: TSESTree.AssignmentPattern,
      type: 'parameter' | 'property',
    ): void {
      context.report({
        node: node.right,
        messageId: 'uselessUndefined',
        data: { type },
        fix: fixer => removeDefault(fixer, node),
      });
    }

reportPreferOptionalSyntax(node: TSESTree.AssignmentPattern): void

Parameters:

  • node TSESTree.AssignmentPattern

Returns: void

Calls:

  • context.report
  • removeDefault
  • fixer.insertTextAfterRange
Code
function reportPreferOptionalSyntax(
      node: TSESTree.AssignmentPattern,
    ): void {
      context.report({
        node: node.right,
        messageId: 'preferOptionalSyntax',
        *fix(fixer) {
          yield removeDefault(fixer, node);

          const { left } = node;
          if (left.type === AST_NODE_TYPES.Identifier) {
            yield fixer.insertTextAfterRange(
              [left.range[0], left.range[0] + left.name.length],
              '?',
            );
          }
        },
      });
    }

removeDefault(fixer: TSESLint.RuleFixer, node: TSESTree.AssignmentPattern): TSESLint.RuleFix

Parameters:

  • fixer TSESLint.RuleFixer
  • node TSESTree.AssignmentPattern

Returns: TSESLint.RuleFix

Calls:

  • fixer.removeRange
Code
function removeDefault(
      fixer: TSESLint.RuleFixer,
      node: TSESTree.AssignmentPattern,
    ): TSESLint.RuleFix {
      const start = node.left.range[1];
      const end = node.range[1];
      return fixer.removeRange([start, end]);
    }

hasPropertyInAllBranches(expression: TSESTree.Expression, propertyName: string): boolean

Parameters:

  • expression TSESTree.Expression
  • propertyName string

Returns: boolean

Calls:

  • expression.properties.some
  • getPropertyName
  • hasPropertyInAllBranches
Code
function hasPropertyInAllBranches(
      expression: TSESTree.Expression,
      propertyName: string,
    ): boolean {
      return (
        (expression.type === AST_NODE_TYPES.ObjectExpression &&
          expression.properties.some(
            prop =>
              prop.type === AST_NODE_TYPES.Property &&
              getPropertyName(prop.key) === propertyName,
          )) ||
        (expression.type === AST_NODE_TYPES.ConditionalExpression &&
          hasPropertyInAllBranches(expression.consequent, propertyName) &&
          hasPropertyInAllBranches(expression.alternate, propertyName))
      );
    }

Type Aliases

MessageId

type MessageId = | 'noStrictNullCheck'
  | 'preferOptionalSyntax'
  | 'uselessDefaultAssignment'
  | 'uselessUndefined';

Options

type Options = [
  {
    allowRuleToRunWithoutStrictNullChecksIKnowWhatIAmDoing?: boolean;
  },
];

Generated by Syntax Scribe