Skip to content

Lodash's mapValues and empty object type interact confusingly #29901

Closed
@seansfkelley

Description

@seansfkelley

I had trouble coming up with a good name and search terms for this issue. It looks like it's triggering some heuristic that is misbehaving and is very strange. Please feel free to rename if you can come up with a better summary for it.

TypeScript Version: 3.3.1

Search Terms: mapvalues ternary side effect unused inference empty object type

Code

// Begin types from Lodash.
interface Dictionary<T> {
  [index: string]: T;
}

interface NumericDictionary<T> {
  [index: number]: T;
}

type ObjectIterator<TObject, TResult> = (value: TObject[keyof TObject], key: string, collection: TObject) => TResult;

type DictionaryIterator<T, TResult> = ObjectIterator<Dictionary<T>, TResult>;

// In lodash.d.ts this function has many overloads, but this seems to be the problematic one.
function mapValues<T, TResult>(obj: Dictionary<T> | NumericDictionary<T> | null | undefined, callback: DictionaryIterator<T, TResult>): Dictionary<TResult> {
  return null as any;
} 
// End types from Lodash.

interface Foo {
    foo: string;
} 

interface Bar {
    bar: string;
}

export function fooToBar(
  foos: Record<string, Foo>,
): Record<string, Bar | null> {
  // The next line, despite being unrelated to the other two lines, causes them to fail.
  // Comment it out to see the function compile erroneously.
  //
  // This behavior only happens when `result` is used as an intermediate: if you return 
  // the ternary directly, the function always compiles.
  //
  // I couldn't find another Lodash function for which this issue reproduced after sampling
  // a few. 
  const wat = mapValues(foos, f => f.foo);
  const result = foos == null ? {} : mapValues(foos, f => f.foo);
  // This line _should_ fail, because `result` is not the right type.
  return result;
}

Expected behavior: fails to compile without the const wat line present.

Actual behavior: only fails to compile when const wat is present.

Playground Link: link

Related Issues:

Metadata

Metadata

Assignees

Labels

Needs InvestigationThis issue needs a team member to investigate its status.

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions