Skip to content

@studnicky/inline-trivial-logic ​

Disallows shim functions that only forward or delegate a value without adding logic. It examines an expression-bodied arrow, a single return, or the exact two-statement reduction var/let/const result = expression; return result; (leading empty statements are ignored). It can report a forwarded identifier, call, awaited expression, chain, or a non-this member expression. Correct remediation rewrites call sites and can change public or virtual dispatch semantics.

Fixable: No · Options: allowLiterals, allowMemberExpressions · Suggested severity: error

Exemptions ​

The rule leaves these shapes alone because they are a value, a contract boundary, or do not have a safe call-site rewrite:

  • factories that create an object, array, or instance; member access rooted at this; and a function returning this;
  • literal and template-literal returns by default, and an identifier that selects one of multiple own parameters rather than forwarding a sole parameter;
  • a function with a type-predicate return annotation;
  • an inline function passed as a call or constructor argument, including through an object or array literal argument;
  • a class function expression or arrow member mandated by an implemented/inherited member, or marked protected or override;
  • calls that read instance state through this or a #private field, or that call through a #private, private, or protected receiver;
  • calls whose arguments are not literals or a one-to-one relay of the function's own parameters — static withCeiling(strategy, ceilingMs) { return (attempt, base) => { const result = Math.min(ceilingMs, strategy(attempt, base)); return result; }; } calls Math.min with a closed-over outer variable and the result of another call, neither a pass-through of the returned arrow's own parameters, so this is a decorator capping a strategy's output, not a shim; satisfiesConstant(value, constantValue) { return Predicates.areDeeplyEqual(value, constantValue); } passes both parameters straight through, unmodified, and stays reported; and
  • a direct call through a locally scoped receiver, where the wrapper preserves that receiver's method binding — a plain-identifier receiver whose own declaration is nested inside an enclosing function, rather than declared at module top level or resolved from a standard-library .d.ts file, holds a runtime-injected value: in packages/resilience/src/retry/retry/Retry.ts:508-516, the private method classifyError holds const classifier = this.errorClassifier;, then when classifier is not itself a function returns classifier.classify(error, attemptNumber) — this cannot become a point-free classifier.classify, because that detaches the method from its classifier receiver, and any implementation of classify reading this internally breaks the next time it runs. A statically-known receiver such as Math.abs(v) or a module-level import does not qualify — nothing is detached by inlining it — so Math.min/Predicates.areDeeplyEqual-shaped calls stay reported regardless of this exemption.

A public zero-argument this.method() call and a direct call that forwards only its own parameters remain reportable shims.

✗ Incorrect ​

ts
// Trivial call-through
function getUser(id: string): Promise<User> {
  return repository.findById(id);
}
ts
// Trivial identifier forward
const wrapValue = (v: string) => v;
ts
// Trivial await forward
async function fetchData(url: string): Promise<Data> {
  return await http.get(url);
}
ts
// The explicit-return-binding spelling remains the same shim
function getUser(id: string): Promise<User> {
  const result = repository.findById(id);
  return result;
}

✓ Correct ​

ts
// Adds validation logic before delegating
function getUser(id: string): Promise<User> {
  validateId(id);
  return repository.findById(id);
}
ts
// Constructs a new object — not trivial
function createUser(name: string): User {
  return new User(name);
}
ts
// Callback position has no call site to inline into
runWhenEnabled(() => service.refresh());
ts
// The arguments do work; they are not a one-to-one forward
function withLimit(value: number, limit: number): number {
  return Math.min(value, limit - 1);
}
ts
// Default literal policy treats this function as the value it produces
function empty(): string {
  return "";
}

Options ​

json
{
  "@studnicky/inline-trivial-logic": [
    "error",
    {
      "allowLiterals": true,
      "allowMemberExpressions": false
    }
  ]
}
OptionTypeDefaultDescription
allowLiteralsbooleantrueAllow functions that return a literal or template-literal value. Set false to report them.
allowMemberExpressionsbooleanfalseAllow functions that return a member expression (e.g. obj.prop).