Skip to content

⬅️ Back to Table of Contents

📄 no-redundant-type-constituents

📊 Analysis Summary

Metric Count
🔧 Functions 11
📦 Imports 11
📊 Variables & Constants 6
📐 Interfaces 3
📑 Type Aliases 1

📚 Table of Contents

🛠️ File Location:

📂 packages/eslint-plugin/src/rules/no-redundant-type-constituents.ts

📤 Default Export

export default createRule({ ... })
Property Value
name 'no-redundant-type-constituents'
meta.type 'suggestion'
meta.docs.description 'Disallow members of unions and intersections that do nothing or override type information'
meta.docs.recommended 'recommended'
meta.docs.requiresTypeChecking true
meta.messages.errorTypeOverrides '{{typeName}}' is an 'error' type that acts as 'any' and overrides all other types in this {{container}} type.
meta.messages.literalOverridden {{literal}} is overridden by {{primitive}} in this union type.
meta.messages.overridden '{{typeName}}' is overridden by other types in this {{container}} type.
meta.messages.overrides '{{typeName}}' overrides all other types in this {{container}} type.
meta.messages.primitiveOverridden {{primitive}} is overridden by the {{literal}} in this intersection type.
meta.schema []
defaultOptions []

Entry point: create — documented under Functions.


📦 Imports

Name Source
AST_NODE_TYPES @typescript-eslint/utils
TSESTree @typescript-eslint/utils
arrayGroupByToMap ../util
createRule ../util
getParserServices ../util
isFunctionOrFunctionType ../util
isTypeAnyType ../util
isTypeBigIntLiteralType ../util
isTypeNeverType ../util
isTypeTemplateLiteralType ../util
isTypeUnknownType ../util

Variables & Constants

Name Type Kind Value Exported
literalToPrimitiveTypeFlags { readonly [x: number]: any; } const { [ts.TypeFlags.BigIntLiteral]: ts.TypeFlags.BigInt, [ts.TypeFlags.BooleanLit...
literalTypeFlags readonly [any, any, any, any, any] const [ ts.TypeFlags.BigIntLiteral, ts.TypeFlags.BooleanLiteral, ts.TypeFlags.Numbe...
primitiveTypeFlags readonly [any, any, any, any] const [ ts.TypeFlags.BigInt, ts.TypeFlags.Boolean, ts.TypeFlags.Number, ts.TypeFlag...
primitiveTypeFlagNames { readonly [x: number]: "string" \| "... const { [ts.TypeFlags.BigInt]: 'bigint', [ts.TypeFlags.Boolean]: 'boolean', [ts.Typ...
primitiveTypeFlagTypes { readonly bigint: any; readonly bool... const { bigint: ts.TypeFlags.BigIntLiteral, boolean: ts.TypeFlags.BooleanLiteral, n...
keywordNodeTypesToTsTypes Map<any, any> const new Map([ [TSESTree.AST_NODE_TYPES.TSAnyKeyword, ts.TypeFlags.Any], [TSESTree...

Functions

create(context: any): { 'TSIntersectionType:exit'(node: TSESTree.TSIntersectionTy…

Parameters:

  • context any

Returns: { 'TSIntersectionType:exit'(node: TSESTree.TSIntersectionType): void; 'TSUnionType:exit'(node: TSESTree.TSUnionType): void; }

Calls:

  • getParserServices (from ../util)
  • keywordNodeTypesToTsTypes.get
  • describeLiteralTypeNode
  • typeNode.types.flatMap
  • services.getTypeAtLocation
  • unionTypePartsUnlessBoolean
  • typeParts.map
  • describeLiteralType
  • typesCache.get
  • getTypeNodeTypePartFlags
  • typesCache.set
  • context.report
  • getTypeNodeTypePartFlagsCached
  • checkIntersectionBottomAndTopTypes
  • addToMapGroup
  • seenUnionTypes.set
  • seenPrimitiveTypes.has
  • Number.isInteger
  • typeValues.map(name => name.typeName).join
  • checkIfUnionsAreAssignable
  • seenLiteralTypes.get
  • matchedLiteralTypes.join
  • isNodeInsideReturnType
  • checkUnionBottomAndTopTypes
  • seenPrimitiveTypes.add
  • arrayGroupByToMap (from ../util)
  • pairs.map(pair => pair.literalValue).join

Internal Comments:

// if any typeNode is TSTypeReference and typePartFlags have more than 1 element, than the referenced type is definitely a union.
/**
         * @example
         * ```ts
         * type F = "a"|2|"b";
         * type I = F & string;
         * ```
         * This function checks if all the union members of `F` are assignable to the other member of `I`. If every member is assignable, then its reported else not.
         */ (x2)
// For each primitive type of all the seen primitive types,
// if there was a literal type seen that overrides it,
// report each of the primitive type's type nodes
// For each primitive type of all the seen literal types,
// if there was a primitive type seen that overrides it,
// upsert the literal text and primitive type under the backing type node
// For each type node that had at least one overridden literal,
// group those literals by their primitive type,
// then report each primitive type with all its literals

Code
create(context) {
    const services = getParserServices(context);
    const typesCache = new Map<TSESTree.TypeNode, TypeFlagsWithName[]>();

    function getTypeNodeTypePartFlags(
      typeNode: TSESTree.TypeNode,
    ): TypeFlagsWithName[] {
      const keywordTypeFlags = keywordNodeTypesToTsTypes.get(typeNode.type);
      if (keywordTypeFlags) {
        return [
          {
            typeFlags: keywordTypeFlags,
            typeName: describeLiteralTypeNode(typeNode),
          },
        ];
      }

      if (
        typeNode.type === AST_NODE_TYPES.TSLiteralType &&
        typeNode.literal.type === AST_NODE_TYPES.Literal
      ) {
        return [
          {
            typeFlags:
              primitiveTypeFlagTypes[
                typeof typeNode.literal
                  .value as keyof typeof primitiveTypeFlagTypes
              ],
            typeName: describeLiteralTypeNode(typeNode),
          },
        ];
      }

      if (typeNode.type === AST_NODE_TYPES.TSUnionType) {
        return typeNode.types.flatMap(getTypeNodeTypePartFlags);
      }

      const nodeType = services.getTypeAtLocation(typeNode);
      const typeParts = unionTypePartsUnlessBoolean(nodeType);

      return typeParts.map(typePart => ({
        typeFlags: typePart.flags,
        typeName: describeLiteralType(typePart),
      }));
    }

    function getTypeNodeTypePartFlagsCached(
      typeNode: TSESTree.TypeNode,
    ): TypeFlagsWithName[] {
      const existing = typesCache.get(typeNode);
      if (existing) {
        return existing;
      }

      const created = getTypeNodeTypePartFlags(typeNode);
      typesCache.set(typeNode, created);
      return created;
    }

    return {
      'TSIntersectionType:exit'(node: TSESTree.TSIntersectionType): void {
        const seenLiteralTypes = new Map<PrimitiveTypeFlag, string[]>();
        const seenPrimitiveTypes = new Map<
          PrimitiveTypeFlag,
          TSESTree.TypeNode[]
        >();
        const seenUnionTypes = new Map<
          TSESTree.TypeNode,
          TypeFlagsWithName[]
        >();

        function checkIntersectionBottomAndTopTypes(
          { typeFlags, typeName }: TypeFlagsWithName,
          typeNode: TSESTree.TypeNode,
        ): boolean {
          for (const [messageId, checkFlag] of [
            ['overrides', ts.TypeFlags.Any],
            ['overrides', ts.TypeFlags.Never],
            ['overridden', ts.TypeFlags.Unknown],
          ] as const) {
            if (typeFlags === checkFlag) {
              context.report({
                node: typeNode,
                messageId:
                  typeFlags === ts.TypeFlags.Any && typeName !== 'any'
                    ? 'errorTypeOverrides'
                    : messageId,
                data: {
                  container: 'intersection',
                  typeName,
                },
              });
              return true;
            }
          }

          return false;
        }

        for (const typeNode of node.types) {
          const typePartFlags = getTypeNodeTypePartFlagsCached(typeNode);

          for (const typePart of typePartFlags) {
            if (checkIntersectionBottomAndTopTypes(typePart, typeNode)) {
              continue;
            }

            for (const literalTypeFlag of literalTypeFlags) {
              if (typePart.typeFlags === literalTypeFlag) {
                addToMapGroup(
                  seenLiteralTypes,
                  literalToPrimitiveTypeFlags[literalTypeFlag],
                  typePart.typeName,
                );
                break;
              }
            }

            for (const primitiveTypeFlag of primitiveTypeFlags) {
              if (typePart.typeFlags === primitiveTypeFlag) {
                addToMapGroup(seenPrimitiveTypes, primitiveTypeFlag, typeNode);
              }
            }
          }
          // if any typeNode is TSTypeReference and typePartFlags have more than 1 element, than the referenced type is definitely a union.
          if (typePartFlags.length >= 2) {
            seenUnionTypes.set(typeNode, typePartFlags);
          }
        }
        /**
         * @example
         * ```ts
         * type F = "a"|2|"b";
         * type I = F & string;
         * ```
         * This function checks if all the union members of `F` are assignable to the other member of `I`. If every member is assignable, then its reported else not.
         */
        const checkIfUnionsAreAssignable = (): undefined => {
          for (const [typeRef, typeValues] of seenUnionTypes) {
            let primitive: number | undefined = undefined;
            for (const { typeFlags } of typeValues) {
              if (
                seenPrimitiveTypes.has(
                  literalToPrimitiveTypeFlags[
                    typeFlags as keyof typeof literalToPrimitiveTypeFlags
                  ],
                )
              ) {
                primitive =
                  literalToPrimitiveTypeFlags[
                    typeFlags as keyof typeof literalToPrimitiveTypeFlags
                  ];
              } else {
                primitive = undefined;
                break;
              }
            }
            if (Number.isInteger(primitive)) {
              context.report({
                node: typeRef,
                messageId: 'primitiveOverridden',
                data: {
                  literal: typeValues.map(name => name.typeName).join(' | '),
                  primitive:
                    primitiveTypeFlagNames[
                      primitive as keyof typeof primitiveTypeFlagNames
                    ],
                },
              });
            }
          }
        };
        if (seenUnionTypes.size > 0) {
          checkIfUnionsAreAssignable();
          return;
        }
        // For each primitive type of all the seen primitive types,
        // if there was a literal type seen that overrides it,
        // report each of the primitive type's type nodes
        for (const [primitiveTypeFlag, typeNodes] of seenPrimitiveTypes) {
          const matchedLiteralTypes = seenLiteralTypes.get(primitiveTypeFlag);
          if (matchedLiteralTypes) {
            for (const typeNode of typeNodes) {
              context.report({
                node: typeNode,
                messageId: 'primitiveOverridden',
                data: {
                  literal: matchedLiteralTypes.join(' | '),
                  primitive: primitiveTypeFlagNames[primitiveTypeFlag],
                },
              });
            }
          }
        }
      },
      'TSUnionType:exit'(node: TSESTree.TSUnionType): void {
        const seenLiteralTypes = new Map<
          PrimitiveTypeFlag,
          TypeNodeWithValue[]
        >();
        const seenPrimitiveTypes = new Set<PrimitiveTypeFlag>();

        function checkUnionBottomAndTopTypes(
          { typeFlags, typeName }: TypeFlagsWithName,
          typeNode: TSESTree.TypeNode,
        ): boolean {
          for (const checkFlag of [
            ts.TypeFlags.Any,
            ts.TypeFlags.Unknown,
          ] as const) {
            if (typeFlags === checkFlag) {
              context.report({
                node: typeNode,
                messageId:
                  typeFlags === ts.TypeFlags.Any && typeName !== 'any'
                    ? 'errorTypeOverrides'
                    : 'overrides',
                data: {
                  container: 'union',
                  typeName,
                },
              });
              return true;
            }
          }

          if (
            typeFlags === ts.TypeFlags.Never &&
            !isNodeInsideReturnType(node)
          ) {
            context.report({
              node: typeNode,
              messageId: 'overridden',
              data: {
                container: 'union',
                typeName: 'never',
              },
            });
            return true;
          }

          return false;
        }

        for (const typeNode of node.types) {
          const typePartFlags = getTypeNodeTypePartFlagsCached(typeNode);

          for (const typePart of typePartFlags) {
            if (checkUnionBottomAndTopTypes(typePart, typeNode)) {
              continue;
            }

            for (const literalTypeFlag of literalTypeFlags) {
              if (typePart.typeFlags === literalTypeFlag) {
                addToMapGroup(
                  seenLiteralTypes,
                  literalToPrimitiveTypeFlags[literalTypeFlag],
                  {
                    literalValue: typePart.typeName,
                    typeNode,
                  },
                );
                break;
              }
            }

            for (const primitiveTypeFlag of primitiveTypeFlags) {
              if ((typePart.typeFlags & primitiveTypeFlag) !== 0) {
                seenPrimitiveTypes.add(primitiveTypeFlag);
              }
            }
          }
        }

        interface TypeFlagWithText {
          literalValue: unknown;
          primitiveTypeFlag: PrimitiveTypeFlag;
        }

        const overriddenTypeNodes = new Map<
          TSESTree.TypeNode,
          TypeFlagWithText[]
        >();

        // For each primitive type of all the seen literal types,
        // if there was a primitive type seen that overrides it,
        // upsert the literal text and primitive type under the backing type node
        for (const [primitiveTypeFlag, typeNodesWithText] of seenLiteralTypes) {
          if (seenPrimitiveTypes.has(primitiveTypeFlag)) {
            for (const { literalValue, typeNode } of typeNodesWithText) {
              addToMapGroup(overriddenTypeNodes, typeNode, {
                literalValue,
                primitiveTypeFlag,
              });
            }
          }
        }

        // For each type node that had at least one overridden literal,
        // group those literals by their primitive type,
        // then report each primitive type with all its literals
        for (const [typeNode, typeFlagsWithText] of overriddenTypeNodes) {
          const grouped = arrayGroupByToMap(
            typeFlagsWithText,
            pair => pair.primitiveTypeFlag,
          );

          for (const [primitiveTypeFlag, pairs] of grouped) {
            context.report({
              node: typeNode,
              messageId: 'literalOverridden',
              data: {
                literal: pairs.map(pair => pair.literalValue).join(' | '),
                primitive: primitiveTypeFlagNames[primitiveTypeFlag],
              },
            });
          }
        }
      },
    };
  }

addToMapGroup(map: Map<Key, Value[]>, key: Key, value: Value): void

Parameters:

  • map Map<Key, Value[]>
  • key Key
  • value Value

Returns: void

Calls:

  • map.get
  • existing.push
  • map.set
Code
function addToMapGroup<Key, Value>(
  map: Map<Key, Value[]>,
  key: Key,
  value: Value,
): void {
  const existing = map.get(key);

  if (existing) {
    existing.push(value);
  } else {
    map.set(key, [value]);
  }
}

describeLiteralType(type: ts.Type): string

Parameters:

  • type ts.Type

Returns: string

Calls:

  • type.isStringLiteral
  • JSON.stringify
  • isTypeBigIntLiteralType (from ../util)
  • type.isLiteral
  • type.value.toString
  • tsutils.isIntrinsicErrorType
  • type.aliasSymbol.escapedName.toString
  • isTypeAnyType (from ../util)
  • isTypeNeverType (from ../util)
  • isTypeUnknownType (from ../util)
  • isTypeTemplateLiteralType (from ../util)
  • tsutils.isTrueLiteralType
  • tsutils.isFalseLiteralType

Internal Comments:

// eslint-disable-next-line @typescript-eslint/no-base-to-string

Code
function describeLiteralType(type: ts.Type): string {
  if (type.isStringLiteral()) {
    return JSON.stringify(type.value);
  }

  if (isTypeBigIntLiteralType(type)) {
    return `${type.value.negative ? '-' : ''}${type.value.base10Value}n`;
  }

  if (type.isLiteral()) {
    // eslint-disable-next-line @typescript-eslint/no-base-to-string
    return type.value.toString();
  }

  if (tsutils.isIntrinsicErrorType(type) && type.aliasSymbol) {
    return type.aliasSymbol.escapedName.toString();
  }

  if (isTypeAnyType(type)) {
    return 'any';
  }

  if (isTypeNeverType(type)) {
    return 'never';
  }

  if (isTypeUnknownType(type)) {
    return 'unknown';
  }

  if (isTypeTemplateLiteralType(type)) {
    return 'template literal type';
  }

  if (isTypeBigIntLiteralType(type)) {
    return `${type.value.negative ? '-' : ''}${type.value.base10Value}n`;
  }

  if (tsutils.isTrueLiteralType(type)) {
    return 'true';
  }

  if (tsutils.isFalseLiteralType(type)) {
    return 'false';
  }

  return 'literal type';
}

describeLiteralTypeNode(typeNode: TSESTree.TypeNode): string

Parameters:

  • typeNode TSESTree.TypeNode

Returns: string

Calls:

  • JSON.stringify
Code
function describeLiteralTypeNode(typeNode: TSESTree.TypeNode): string {
  switch (typeNode.type) {
    case AST_NODE_TYPES.TSAnyKeyword:
      return 'any';
    case AST_NODE_TYPES.TSBooleanKeyword:
      return 'boolean';
    case AST_NODE_TYPES.TSNeverKeyword:
      return 'never';
    case AST_NODE_TYPES.TSNumberKeyword:
      return 'number';
    case AST_NODE_TYPES.TSStringKeyword:
      return 'string';
    case AST_NODE_TYPES.TSUnknownKeyword:
      return 'unknown';
    case AST_NODE_TYPES.TSLiteralType:
      switch (typeNode.literal.type) {
        case TSESTree.AST_NODE_TYPES.Literal:
          switch (typeof typeNode.literal.value) {
            case 'bigint':
              return `${typeNode.literal.value < 0 ? '-' : ''}${
                typeNode.literal.value
              }n`;
            case 'string':
              return JSON.stringify(typeNode.literal.value);
            default:
              return `${typeNode.literal.value}`;
          }
        case TSESTree.AST_NODE_TYPES.TemplateLiteral:
          return 'template literal type';
      }
  }

  return 'literal type';
}

isNodeInsideReturnType(node: TSESTree.TSUnionType): boolean

Parameters:

  • node TSESTree.TSUnionType

Returns: boolean

Calls:

  • isFunctionOrFunctionType (from ../util)
Code
function isNodeInsideReturnType(node: TSESTree.TSUnionType): boolean {
  return (
    node.parent.type === AST_NODE_TYPES.TSTypeAnnotation &&
    isFunctionOrFunctionType(node.parent.parent)
  );
}

unionTypePartsUnlessBoolean(type: ts.Type): ts.Type[]

Tags: @remarks TypeScript stores boolean types as the union false | true, always.

Raw JSDoc
/**
 * @remarks TypeScript stores boolean types as the union false | true, always.
 */

Calls:

  • type.isUnion
  • tsutils.isFalseLiteralType
  • tsutils.isTrueLiteralType
  • tsutils.unionConstituents
Code
function unionTypePartsUnlessBoolean(type: ts.Type): ts.Type[] {
  return type.isUnion() &&
    type.types.length === 2 &&
    tsutils.isFalseLiteralType(type.types[0]) &&
    tsutils.isTrueLiteralType(type.types[1])
    ? [type]
    : tsutils.unionConstituents(type);
}

Internal helpers

Declared inside another function in this file.

getTypeNodeTypePartFlags(typeNode: TSESTree.TypeNode): TypeFlagsWithName[]

Parameters:

  • typeNode TSESTree.TypeNode

Returns: TypeFlagsWithName[]

Calls:

  • keywordNodeTypesToTsTypes.get
  • describeLiteralTypeNode
  • typeNode.types.flatMap
  • services.getTypeAtLocation
  • unionTypePartsUnlessBoolean
  • typeParts.map
  • describeLiteralType
Code
function getTypeNodeTypePartFlags(
      typeNode: TSESTree.TypeNode,
    ): TypeFlagsWithName[] {
      const keywordTypeFlags = keywordNodeTypesToTsTypes.get(typeNode.type);
      if (keywordTypeFlags) {
        return [
          {
            typeFlags: keywordTypeFlags,
            typeName: describeLiteralTypeNode(typeNode),
          },
        ];
      }

      if (
        typeNode.type === AST_NODE_TYPES.TSLiteralType &&
        typeNode.literal.type === AST_NODE_TYPES.Literal
      ) {
        return [
          {
            typeFlags:
              primitiveTypeFlagTypes[
                typeof typeNode.literal
                  .value as keyof typeof primitiveTypeFlagTypes
              ],
            typeName: describeLiteralTypeNode(typeNode),
          },
        ];
      }

      if (typeNode.type === AST_NODE_TYPES.TSUnionType) {
        return typeNode.types.flatMap(getTypeNodeTypePartFlags);
      }

      const nodeType = services.getTypeAtLocation(typeNode);
      const typeParts = unionTypePartsUnlessBoolean(nodeType);

      return typeParts.map(typePart => ({
        typeFlags: typePart.flags,
        typeName: describeLiteralType(typePart),
      }));
    }

getTypeNodeTypePartFlagsCached(typeNode: TSESTree.TypeNode): TypeFlagsWithName[]

Parameters:

  • typeNode TSESTree.TypeNode

Returns: TypeFlagsWithName[]

Calls:

  • typesCache.get
  • getTypeNodeTypePartFlags
  • typesCache.set
Code
function getTypeNodeTypePartFlagsCached(
      typeNode: TSESTree.TypeNode,
    ): TypeFlagsWithName[] {
      const existing = typesCache.get(typeNode);
      if (existing) {
        return existing;
      }

      const created = getTypeNodeTypePartFlags(typeNode);
      typesCache.set(typeNode, created);
      return created;
    }

checkIntersectionBottomAndTopTypes({ typeFlags, typeName }: TypeFlagsWithName, typeNode: TSESTree.TypeNode): boolean

Parameters:

  • { typeFlags, typeName } TypeFlagsWithName
  • typeNode TSESTree.TypeNode

Returns: boolean

Calls:

  • context.report
Code
function checkIntersectionBottomAndTopTypes(
          { typeFlags, typeName }: TypeFlagsWithName,
          typeNode: TSESTree.TypeNode,
        ): boolean {
          for (const [messageId, checkFlag] of [
            ['overrides', ts.TypeFlags.Any],
            ['overrides', ts.TypeFlags.Never],
            ['overridden', ts.TypeFlags.Unknown],
          ] as const) {
            if (typeFlags === checkFlag) {
              context.report({
                node: typeNode,
                messageId:
                  typeFlags === ts.TypeFlags.Any && typeName !== 'any'
                    ? 'errorTypeOverrides'
                    : messageId,
                data: {
                  container: 'intersection',
                  typeName,
                },
              });
              return true;
            }
          }

          return false;
        }

checkIfUnionsAreAssignable(): undefined

Returns: undefined

Calls:

  • seenPrimitiveTypes.has
  • Number.isInteger
  • context.report
  • typeValues.map(name => name.typeName).join
Code
(): undefined => {
          for (const [typeRef, typeValues] of seenUnionTypes) {
            let primitive: number | undefined = undefined;
            for (const { typeFlags } of typeValues) {
              if (
                seenPrimitiveTypes.has(
                  literalToPrimitiveTypeFlags[
                    typeFlags as keyof typeof literalToPrimitiveTypeFlags
                  ],
                )
              ) {
                primitive =
                  literalToPrimitiveTypeFlags[
                    typeFlags as keyof typeof literalToPrimitiveTypeFlags
                  ];
              } else {
                primitive = undefined;
                break;
              }
            }
            if (Number.isInteger(primitive)) {
              context.report({
                node: typeRef,
                messageId: 'primitiveOverridden',
                data: {
                  literal: typeValues.map(name => name.typeName).join(' | '),
                  primitive:
                    primitiveTypeFlagNames[
                      primitive as keyof typeof primitiveTypeFlagNames
                    ],
                },
              });
            }
          }
        }

checkUnionBottomAndTopTypes({ typeFlags, typeName }: TypeFlagsWithName, typeNode: TSESTree.TypeNode): boolean

Parameters:

  • { typeFlags, typeName } TypeFlagsWithName
  • typeNode TSESTree.TypeNode

Returns: boolean

Calls:

  • context.report
  • isNodeInsideReturnType
Code
function checkUnionBottomAndTopTypes(
          { typeFlags, typeName }: TypeFlagsWithName,
          typeNode: TSESTree.TypeNode,
        ): boolean {
          for (const checkFlag of [
            ts.TypeFlags.Any,
            ts.TypeFlags.Unknown,
          ] as const) {
            if (typeFlags === checkFlag) {
              context.report({
                node: typeNode,
                messageId:
                  typeFlags === ts.TypeFlags.Any && typeName !== 'any'
                    ? 'errorTypeOverrides'
                    : 'overrides',
                data: {
                  container: 'union',
                  typeName,
                },
              });
              return true;
            }
          }

          if (
            typeFlags === ts.TypeFlags.Never &&
            !isNodeInsideReturnType(node)
          ) {
            context.report({
              node: typeNode,
              messageId: 'overridden',
              data: {
                container: 'union',
                typeName: 'never',
              },
            });
            return true;
          }

          return false;
        }

Interfaces

TypeFlagsWithName

Interface Code
interface TypeFlagsWithName {
  typeFlags: ts.TypeFlags;
  typeName: string;
}

Properties

Name Type Optional Description
typeFlags ts.TypeFlags not shown
typeName string not shown

TypeNodeWithValue

Interface Code
interface TypeNodeWithValue {
  literalValue: unknown;
  typeNode: TSESTree.TypeNode;
}

Properties

Name Type Optional Description
literalValue unknown not shown
typeNode TSESTree.TypeNode not shown

TypeFlagWithText

Interface Code
interface TypeFlagWithText {
          literalValue: unknown;
          primitiveTypeFlag: PrimitiveTypeFlag;
        }

Properties

Name Type Optional Description
literalValue unknown not shown
primitiveTypeFlag PrimitiveTypeFlag not shown

Type Aliases

PrimitiveTypeFlag

type PrimitiveTypeFlag = (typeof primitiveTypeFlags)[number];

Generated by Syntax Scribe