Skip to content

Function.prototype.bind typings do not work properly when supplied a function with variadic arguments. #42196

Closed
@benlesh

Description

@benlesh

Bug Report

If you pass a function that might behave differently when supplied different arguments, the resulting type does not properly accommodate all call patterns.

I ran into this while trying to figure out how TypeScript handled situations similar to RxJS's bindNodeCallback and bindCallback, which suffers from similar problems.

🔎 Search Terms

  • bind
  • bind "Arguments for the rest parameter"

🕗 Version & Regression Information

versions 3.3.* - 4.1.3

  • This is the behavior in every version I tried, and I reviewed the FAQ for entries about (I have no idea where the FAQ is, reporting anyway, because this is friction)

⏯ Playground Link

Playground link with relevant code

💻 Code

interface A {
    a: string;
}
interface B {
    b: string;
}
interface C {
    c: string;
}
interface D {
    d: string;
}

const a: A = { a: 'a' };
const b: B = { b: 'b' };
const c: C = { c: 'c' };
const d: D = { d: 'd' };

// Let's say these are the only valid ways to
// call our `test` function:
function test(a: A, b: B): A; // 1
function test(a: A, c: C): B; // 2
function test(a: A, b: B, d: D): C; // 3

// "impl" here
function test(a: A, bOrC: B | C, d?: D): A | B | C {
    if (isA(a)) {
        if (isB(bOrC)) {
            if (isD(d)) {
                return { c: 'test' }; // 3
            } else {
                return { a: 'test' }; // 1
            }
        }
        if (isC(bOrC)) {
            return { b: 'test' }; // 2
        }
    }
    throw new Error('wrong call');
}

function isA(input: any): input is A {
    return input && 'a' in input && typeof input['a'] === 'string';
}

function isB(input: any): input is B {
    return input && 'b' in input && typeof input['b'] === 'string';
}

function isC(input: any): input is C {
    return input && 'c' in input && typeof input['c'] === 'string';
}

function isD(input: any): input is D {
    return input && 'd' in input && typeof input['d'] === 'string';
}


const x = test.bind(null, a, b);

const r = x();

console.log(r);

🙁 Actual behavior

image

I got a compilation error for a perfectly valid call of my bound function.

🙂 Expected behavior

The return type (the type of r) should be C, and the code should compile successfully.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Design LimitationConstraints of the existing architecture prevent this from being fixed

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions