question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. Itย collects links to all the places you might be looking at while hunting down a tough bug.

And, if youโ€™re still stuck at the end, weโ€™re happy to hop on a call to see how we can help out.

Overload gets lost in mapped type with conditional type

See original GitHub issue

TypeScript Version: 3.4.0-dev.201xxxxx

Search Terms: mapped type overload

Code

interface Overloads {
  foo(a: string): void;
  foo(a: number, b: string): void;
}

/** Converts all properties of an object to Promises and all methods to return Promises */
type ProxiedObject<T> = {
  [P in keyof T]: T[P] extends (...args: infer Arguments) => infer R
    ? (...args: Arguments) => Promise<R>
    : Promise<T[P]>
};

declare let x: ProxiedObject<Overloads>;
x.foo("abc"); // Error: [ts] Expected 2 arguments, but got 1. [2554]
x.foo(123, "abc");

Expected behavior: No error, overload should be maintained.

This makes it impossible to use this pattern with popular types that contain overloads, like Rx Observable pipe()/subscribe(). The ProxiedObject type is used in https://github.com/GoogleChromeLabs/comlink.

Actual behavior: Overload gets lost, compile error when trying to call the first overload.

Playground Link: link

Issue Analytics

  • State:open
  • Created 5 years ago
  • Reactions:28
  • Comments:12 (3 by maintainers)

github_iconTop GitHub Comments

12reactions
brunolemoscommented, Feb 16, 2019

Not sure if itโ€™s the same issue but I came here to report this behavior:

type Post = { body: string }
type Member = { name: string }

type methods = {
    on(event: 'new_post', payload: Post): void
    on(event: 'member_add', payload: Member): void
}

type Params = Parameters<methods['on']>
// Expected Params type: ["new_post", Post] | ["member_add", Member]
// Current behavior: ["member_add", Member] (only gets the last one)

Playground

_Related use case: https://github.com/probot/probot/pull/858_

9reactions
felixfbeckercommented, Feb 4, 2019

But that was before we had tuple types. This overload:

interface Overloads {
  foo(a: string): void;
  foo(a: number, b: string): void;
}

is equivalent to

interface NoOverloads {
  foo(...args: [string] | [number, string]): void;
}

which works correctly. I would use that workaround, but I donโ€™t have control over libraries that use overloads. I would at least expect the compiler to treat the above interface equivalently to the below.

If the return type is different, itโ€™s also possible with conditional types:

interface Overloads {
  foo(a: string): string;
  foo(a: number, b: string): number;
}
interface NoOverloads {
  foo<P>(...params: P): P extends [number, string] ? number : string;
}

So I donโ€™t see a reason why overloads would still be impossible for the compiler to handle

Read more comments on GitHub >

github_iconTop Results From Across the Web

Create a mapped type from an interface with overloaded ...
I want to create a mapped type when applied to the interface above ... from the original type, which just gets me back...
Read more >
Conditional types in TypeScript - Artsy Engineering
Overloading involves providing multiple type signatures for a single function, ... This extends keyword is the heart of a conditional type.
Read more >
What Are Function Overloads in TypeScript?
An error occurs when an implementation signature function is called with an argument of the type corresponding to the implementation signature.ย ...
Read more >
Documentation - Advanced Types - TypeScript
If the mapped type is not homomorphic you'll have to give an explicit type parameter to your unwrapping function. Conditional Types. A conditional...
Read more >
3. Data model โ€” Python 3.11.1 documentation
Objects, values and types: Objects are Python's abstraction for data. ... provide additional examples of mapping types, as does the collections module.
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found