R07SAFEfunction

Return Type Narrowed

Flags when a function's return type becomes more specific. Callers expecting the broader type are safe because the narrower type satisfies the original contract.


Applies to

TypeScriptPythonGoJavaRust

Why it matters

Narrowing a return type is safe because any value of the narrower type is also a valid value of the broader type. A function that previously returned string | number now returning just string will not break any caller that handles both types.

Example

Before (string | number)
// config.ts
export function getValue(key: string): string | number {
  return store.get(key);
}
After (string only)
// config.ts (SAFE)
export function getValue(key: string): string {
  return String(store.get(key)); // always returns string now
}

What you see in the terminal

$ npx dg check

  [SAFE] getValue (signature_change)
  src/config.ts:2
  Return type narrowed from 'string | number' to 'string'. Callers are unaffected.

How detection works

The classifier detects when the new return type is a subset of the old return type (fewer union members, removed null, etc.) and reports it as safe.

Real-world scenario

A configuration function previously returned both strings and numbers. The team normalizes it to always return strings for consistency. Callers handling `string | number` already handle strings, so no breakage.

Edge cases

  • Removing null from a return type (T | null -> T) is covered by this rule
  • Going from 'any' to a specific type is technically narrowing but may break callers relying on 'any' behavior