Skip to content

⬅️ Back to Table of Contents

πŸ“„ util/misc

πŸ“Š Analysis Summary

Metric Count
πŸ”§ Functions 15
πŸ“¦ Imports 7
πŸ“Š Variables & Constants 1
πŸ“‘ Type Aliases 4
🎯 Enums 1

πŸ“š Table of Contents

πŸ› οΈ File Location:

πŸ“‚ packages/eslint-plugin/src/util/misc.ts

πŸ“¦ Imports

Name Source
TSESLint @typescript-eslint/utils
TSESTree @typescript-eslint/utils
RuleContext @typescript-eslint/utils/ts-eslint
requiresQuoting @typescript-eslint/type-utils
AST_NODE_TYPES @typescript-eslint/utils
getStaticValue ./astUtils
isParenthesized ./astUtils

Variables & Constants

Name Type Kind Value Exported
DEFINITION_EXTENSIONS readonly [any, any, any] const [ ts.Extension.Dts, ts.Extension.Dcts, ts.Extension.Dmts, ] as const βœ—

Functions

isDefinitionFile(fileName: string): boolean

Check if the context file name is .d.ts or .d.tsx

Raw JSDoc
/**
 * Check if the context file name is *.d.ts or *.d.tsx
 */

Calls:

  • fileName.toLowerCase
  • lowerFileName.endsWith
  • /\.d\.(ts|cts|mts|.*\.ts)$/.test
Code
export function isDefinitionFile(fileName: string): boolean {
  const lowerFileName = fileName.toLowerCase();
  for (const definitionExt of DEFINITION_EXTENSIONS) {
    if (lowerFileName.endsWith(definitionExt)) {
      return true;
    }
  }

  return /\.d\.(ts|cts|mts|.*\.ts)$/.test(lowerFileName);
}

upperCaseFirst(str: string): string

Upper cases the first character or the string

Raw JSDoc
/**
 * Upper cases the first character or the string
 */

Calls:

  • str[0].toUpperCase
  • str.slice
Code
export function upperCaseFirst(str: string): string {
  return str[0].toUpperCase() + str.slice(1);
}

arrayGroupByToMap(array: T[], getKey: (item: T) => Key): Map<Key, T[]>

Parameters:

  • array T[]
  • getKey (item: T) => Key

Returns: Map<Key, T[]>

Calls:

  • getKey
  • groups.get
  • existing.push
  • groups.set
Code
export function arrayGroupByToMap<T, Key extends number | string>(
  array: T[],
  getKey: (item: T) => Key,
): Map<Key, T[]> {
  const groups = new Map<Key, T[]>();

  for (const item of array) {
    const key = getKey(item);
    const existing = groups.get(key);

    if (existing) {
      existing.push(item);
    } else {
      groups.set(key, [item]);
    }
  }

  return groups;
}

arraysAreEqual(a: T[] | undefined, b: T[] | undefined, eq: (a: T, b: T) => boolean): boolean

Parameters:

  • a T[] | undefined
  • b T[] | undefined
  • eq (a: T, b: T) => boolean

Returns: boolean

Calls:

  • a.every
  • eq
Code
export function arraysAreEqual<T>(
  a: T[] | undefined,
  b: T[] | undefined,
  eq: (a: T, b: T) => boolean,
): boolean {
  return (
    a === b ||
    (a != null && a.length === b?.length && a.every((x, idx) => eq(x, b[idx])))
  );
}

findFirstResult(inputs: T[], getResult: (t: T) => U | undefined): U | undefined

Returns the first non-undefined result.

Raw JSDoc
/** Returns the first non-`undefined` result. */

Calls:

  • getResult

Internal Comments:

// eslint-disable-next-line @typescript-eslint/internal/eqeq-nullish

Code
export function findFirstResult<T, U>(
  inputs: T[],
  getResult: (t: T) => U | undefined,
): U | undefined {
  for (const element of inputs) {
    const result = getResult(element);
    // eslint-disable-next-line @typescript-eslint/internal/eqeq-nullish
    if (result !== undefined) {
      return result;
    }
  }
  return undefined;
}

getNameFromIndexSignature(node: TSESTree.TSIndexSignature): string

Gets a string representation of the name of the index signature.

Raw JSDoc
/**
 * Gets a string representation of the name of the index signature.
 */

Calls:

  • node.parameters.find
Code
export function getNameFromIndexSignature(
  node: TSESTree.TSIndexSignature,
): string {
  const propName: TSESTree.PropertyName | undefined = node.parameters.find(
    (parameter: TSESTree.Parameter): parameter is TSESTree.Identifier =>
      parameter.type === AST_NODE_TYPES.Identifier,
  );
  return propName ? propName.name : '(index signature)';
}

getNameFromMember(member: | TSESTree.AccessorProperty | TSESTree.…, sourceCode: TSESLint.SourceCode): { name: string; type: MemberNameType }

Gets a string name representation of the name of the given MethodDefinition or PropertyDefinition node, with handling for computed property names.

Raw JSDoc
/**
 * Gets a string name representation of the name of the given MethodDefinition
 * or PropertyDefinition node, with handling for computed property names.
 */

Calls:

  • requiresQuoting (from @typescript-eslint/type-utils)
  • sourceCode.text.slice
Code
export function getNameFromMember(
  member:
    | TSESTree.AccessorProperty
    | TSESTree.MethodDefinition
    | TSESTree.Property
    | TSESTree.PropertyDefinition
    | TSESTree.TSAbstractAccessorProperty
    | TSESTree.TSAbstractMethodDefinition
    | TSESTree.TSAbstractPropertyDefinition
    | TSESTree.TSMethodSignature
    | TSESTree.TSPropertySignature,
  sourceCode: TSESLint.SourceCode,
): { name: string; type: MemberNameType } {
  if (member.key.type === AST_NODE_TYPES.Identifier) {
    return {
      name: member.key.name,
      type: MemberNameType.Normal,
    };
  }
  if (member.key.type === AST_NODE_TYPES.PrivateIdentifier) {
    return {
      name: `#${member.key.name}`,
      type: MemberNameType.Private,
    };
  }
  if (member.key.type === AST_NODE_TYPES.Literal) {
    const name = `${member.key.value}`;
    if (requiresQuoting(name)) {
      return {
        name: `"${name}"`,
        type: MemberNameType.Quoted,
      };
    }
    return {
      name,
      type: MemberNameType.Normal,
    };
  }

  return {
    name: sourceCode.text.slice(...member.key.range),
    type: MemberNameType.Expression,
  };
}

getEnumNames(myEnum: Record<T, unknown>): T[]

Parameters:

  • myEnum Record<T, unknown>

Returns: T[]

Calls:

  • Object.keys(myEnum).filter
  • isNaN
  • Number
Code
export function getEnumNames<T extends string>(
  myEnum: Record<T, unknown>,
): T[] {
  return Object.keys(myEnum).filter(x => isNaN(Number(x))) as T[];
}

formatWordList(words: string[]): string

Given an array of words, returns an English-friendly concatenation, separated with commas, with the and clause inserted before the last item.

Example: ['foo', 'bar', 'baz' ] returns the string "foo, bar, and baz".

Raw JSDoc
/**
 * Given an array of words, returns an English-friendly concatenation, separated with commas, with
 * the `and` clause inserted before the last item.
 *
 * Example: ['foo', 'bar', 'baz' ] returns the string "foo, bar, and baz".
 */

Calls:

  • [words.slice(0, -1).join(', '), words.slice(-1)[0]].join
  • words.slice(0, -1).join
  • words.slice
Code
export function formatWordList(words: string[]): string {
  if (!words.length) {
    return '';
  }

  if (words.length === 1) {
    return words[0];
  }

  return [words.slice(0, -1).join(', '), words.slice(-1)[0]].join(' and ');
}

findLastIndex(members: T[], predicate: (member: T) => boolean | null | undefin…): number

Iterates the array in reverse and returns the index of the first element it finds which passes the predicate function.

Returns: undefined Returns the index of the element if it finds it or -1 otherwise.

Raw JSDoc
/**
 * Iterates the array in reverse and returns the index of the first element it
 * finds which passes the predicate function.
 *
 * @returns Returns the index of the element if it finds it or -1 otherwise.
 */

Calls:

  • predicate
Code
export function findLastIndex<T>(
  members: T[],
  predicate: (member: T) => boolean | null | undefined,
): number {
  let idx = members.length - 1;

  while (idx >= 0) {
    const valid = predicate(members[idx]);
    if (valid) {
      return idx;
    }
    idx--;
  }

  return -1;
}

typeNodeRequiresParentheses(node: TSESTree.TypeNode, text: string): boolean

Parameters:

  • node TSESTree.TypeNode
  • text string

Returns: boolean

Calls:

  • text.startsWith
Code
export function typeNodeRequiresParentheses(
  node: TSESTree.TypeNode,
  text: string,
): boolean {
  return (
    node.type === AST_NODE_TYPES.TSFunctionType ||
    node.type === AST_NODE_TYPES.TSConstructorType ||
    node.type === AST_NODE_TYPES.TSConditionalType ||
    (node.type === AST_NODE_TYPES.TSUnionType && text.startsWith('|')) ||
    (node.type === AST_NODE_TYPES.TSIntersectionType && text.startsWith('&'))
  );
}

isRestParameterDeclaration(decl: ts.Declaration): boolean

Parameters:

  • decl ts.Declaration

Returns: boolean

Calls:

  • ts.isParameter
Code
export function isRestParameterDeclaration(decl: ts.Declaration): boolean {
  return ts.isParameter(decl) && decl.dotDotDotToken != null;
}

isParenlessArrowFunction(node: TSESTree.ArrowFunctionExpression, sourceCode: TSESLint.SourceCode): boolean

Parameters:

  • node TSESTree.ArrowFunctionExpression
  • sourceCode TSESLint.SourceCode

Returns: boolean

Calls:

  • isParenthesized (from ./astUtils)
Code
export function isParenlessArrowFunction(
  node: TSESTree.ArrowFunctionExpression,
  sourceCode: TSESLint.SourceCode,
): boolean {
  return (
    node.params.length === 1 && !isParenthesized(node.params[0], sourceCode)
  );
}

getStaticMemberAccessValue(node: NodeWithKey, { sourceCode }: RuleContext<string, unknown[]>): string | symbol | undefined

Gets a member being accessed or declared if its value can be determined statically, and resolves it to the string or symbol value that will be used as the actual member access key at runtime. Otherwise, returns undefined.

x.member // returns 'member'
^^^^^^^^

x?.member // returns 'member' (optional chaining is treated the same)
^^^^^^^^^

x['value'] // returns 'value'
^^^^^^^^^^

x[Math.random()] // returns undefined (not a static value)
^^^^^^^^^^^^^^^^

arr[0] // returns '0' (NOT 0)
^^^^^^

arr[0n] // returns '0' (NOT 0n)
^^^^^^^

const s = Symbol.for('symbolName')
x[s] // returns `Symbol.for('symbolName')` (since it's a static/global symbol)
^^^^

const us = Symbol('symbolName')
x[us] // returns undefined (since it's a unique symbol, so not statically analyzable)
^^^^^

var object = {
    1234: '4567', // returns '1234' (NOT 1234)
    ^^^^^^^^^^^^
    method() { } // returns 'method'
    ^^^^^^^^^^^^
}

class WithMembers {
    foo: string // returns 'foo'
    ^^^^^^^^^^^
}
Raw JSDoc
/**
 * Gets a member being accessed or declared if its value can be determined statically, and
 * resolves it to the string or symbol value that will be used as the actual member
 * access key at runtime. Otherwise, returns `undefined`.
 *
 * ```ts
 * x.member // returns 'member'
 * ^^^^^^^^
 *
 * x?.member // returns 'member' (optional chaining is treated the same)
 * ^^^^^^^^^
 *
 * x['value'] // returns 'value'
 * ^^^^^^^^^^
 *
 * x[Math.random()] // returns undefined (not a static value)
 * ^^^^^^^^^^^^^^^^
 *
 * arr[0] // returns '0' (NOT 0)
 * ^^^^^^
 *
 * arr[0n] // returns '0' (NOT 0n)
 * ^^^^^^^
 *
 * const s = Symbol.for('symbolName')
 * x[s] // returns `Symbol.for('symbolName')` (since it's a static/global symbol)
 * ^^^^
 *
 * const us = Symbol('symbolName')
 * x[us] // returns undefined (since it's a unique symbol, so not statically analyzable)
 * ^^^^^
 *
 * var object = {
 *     1234: '4567', // returns '1234' (NOT 1234)
 *     ^^^^^^^^^^^^
 *     method() { } // returns 'method'
 *     ^^^^^^^^^^^^
 * }
 *
 * class WithMembers {
 *     foo: string // returns 'foo'
 *     ^^^^^^^^^^^
 * }
 * ```
 */

Calls:

  • getStaticValue (from ./astUtils)
  • sourceCode.getScope
  • String
Code
export function getStaticMemberAccessValue(
  node: NodeWithKey,
  { sourceCode }: RuleContext<string, unknown[]>,
): string | symbol | undefined {
  const key =
    node.type === AST_NODE_TYPES.MemberExpression ? node.property : node.key;
  const { type } = key;
  if (
    !node.computed &&
    (type === AST_NODE_TYPES.Identifier ||
      type === AST_NODE_TYPES.PrivateIdentifier)
  ) {
    return key.name;
  }
  const result = getStaticValue(key, sourceCode.getScope(node));
  if (!result) {
    return undefined;
  }
  const { value } = result;
  return typeof value === 'symbol' ? value : String(value);
}

isStaticMemberAccessOfValue(memberExpression: NodeWithKey, context: RuleContext<string, unknown[]>, values: (string | symbol)[]): boolean

Parameters:

  • memberExpression NodeWithKey
  • context RuleContext<string, unknown[]>
  • values (string | symbol)[]

Returns: boolean

Calls:

  • (values as (string | symbol | undefined)[]).includes
Code
(
  memberExpression: NodeWithKey,
  context: RuleContext<string, unknown[]>,
  ...values: (string | symbol)[]
): boolean =>
  (values as (string | symbol | undefined)[]).includes(
    getStaticMemberAccessValue(memberExpression, context),
  )

Type Aliases

Equal<T>

/* Return true if both parameters are equal. /

type Equal<T> = (a: T, b: T) => boolean;

ExcludeKeys<Obj extends Record<string, unknown>, Keys extends keyof Obj>

type ExcludeKeys<Obj extends Record<string, unknown>, Keys extends keyof Obj> = { [k in Exclude<keyof Obj, Keys>]: Obj[k] };

RequireKeys<Obj extends Record<string, unknown>, Keys extends keyof Obj>

type RequireKeys<Obj extends Record<string, unknown>, Keys extends keyof Obj> = { [k in Keys]-?: Exclude<Obj[k], undefined> } & ExcludeKeys<Obj, Keys>;

NodeWithKey

type NodeWithKey = | TSESTree.AccessorProperty
  | TSESTree.MemberExpression
  | TSESTree.MethodDefinition
  | TSESTree.Property
  | TSESTree.PropertyDefinition
  | TSESTree.TSAbstractMethodDefinition
  | TSESTree.TSAbstractPropertyDefinition;

Enums

enum MemberNameType

Enum Code
export enum MemberNameType {
  Private = 1,
  Quoted = 2,
  Normal = 3,
  Expression = 4,
}

Members

Name Value Description
Private 1 not shown
Quoted 2 not shown
Normal 3 not shown
Expression 4 not shown

Generated by Syntax Scribe