Question Details

No question body available.

Tags

typescript

Answers (1)

Accepted Answer Available
Accepted Answer
February 16, 2026 Score: 3 Rep: 339,996 Quality: Expert Completeness: 80%

An intersection of function types is identical in call behavior to an overloaded function. So you're really asking how TypeScript resolves calls to overloaded functions and your example looks like

interface AB {
  (a: 'foo'): string;
  (a: string): string | undefined;
}
const f1: AB = (a: string) => ''
const c1 = f1('foo') // string
const c2 = f1('bar') // string | undefined

interface BA { (a: string): string | undefined; (a: 'foo'): string; } const f2: BA = (a: string) => '' const c3 = f2('foo') // string const c4 = f2('bar') // string | undefined

Generally overload calls are resolved by the first match in declaration order, but it seems that there is an exception made for call signatures whose parameters contain single literal types, as described in the resolution to microsoft/TypeScript#1133 as implemented in microsoft/TypeScript#1562 and later discussed in microsoft/TypeScript#9443 and microsoft/TypeScript#46376.

It looks like such call signatures are consulted first... that is, the call signatures are effectively reordered. So therefore in the particular example you've chosen, AB and BA behave the same, since in both cases the "foo" parameter signature is checked before the string one. It's an exception to the rule.

To see overloads behave the "normal" way you should try with types that aren't single literals. For example:

interface AB {
  (a: string): string;
  (a: string | number): string | undefined;
}
const f1: AB = (a: string | number) => ''
const c1 = f1('foo') // string
const c2 = f1(0) // string | undefined

interface BA { (a: string | number): string | undefined; (a: string): string; } const f2: BA = (a: string | number) => '' const c3 = f2('foo') // string | undefined