Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Super constructor spread #11679

Closed
anvish opened this issue Oct 17, 2016 · 3 comments
Closed

Super constructor spread #11679

anvish opened this issue Oct 17, 2016 · 3 comments
Labels
Working as Intended The behavior described is the intended behavior; this is not a bug

Comments

@anvish
Copy link

anvish commented Oct 17, 2016

TypeScript Version: 2.0.3

Code

class A {
    constructor(a: number, b: string) { }
}

class B extends A {
    constructor(...args) {
        super(...args) // Supplied parameters do not match any signature of call target.
    }
}

Expected behavior:
It's possible to pass arguments to super constructor without specifying them explicitly.
E.g. when extending classes of external framework, like React, which calls constructors.

Actual behavior:
Error: Supplied parameters do not match any signature of call target

@yortus
Copy link
Contributor

yortus commented Oct 17, 2016

I think the compiler is correct to flag the example as non-type-safe. You could instantiate B with zero arguments, one argument, ten arguments, and each argument can be any type. Those same arguments will then be passed through to A's constructor. But A expects exactly two arguments of specific types, so this pattern is not type-safe at all.

You'd get the same error if you wrote new A(42) or new A(1, 'foo', true), even though B's constructor would allow any of those.

@remojansen
Copy link
Contributor

If the constructor of A can take an undetermined number of arguments, then it would make sense to use ...:

class A {
   values: any[];
    constructor(...args: any[]) {
        this.values = args;
    }
}

class B extends A {
    constructor(...args: any[]) {
        super(args);
    }
}

However, in this case it looks like the number of arguments of A is determined. So it would be better to do the following:

class A {
    constructor(a: number, b: string) {}
}

class B extends A {
    constructor(...args: any[]) {
        if (args.length < 2) throw new Error();
        let a: number = args[0];
        let b: string = args[1];
        super(a, b);
    }
}

If the number of constructor arguments in B can be determined, then I would recommend to avoid using ... on both A and B.

class A {
    constructor(a: number, b: string) {}
}

class B extends A {
    constructor(a: number, b: string) {
        super(a, b);
    }
}

The ... operator will save you writing some code but you are losing certain level of security provided by the type system.

@DanielRosenwasser
Copy link
Member

For the record, if you just didn't write a constructor at all, TypeScript would just "inherit" the constructor. See here.

@DanielRosenwasser DanielRosenwasser added the Working as Intended The behavior described is the intended behavior; this is not a bug label Oct 17, 2016
@microsoft microsoft locked and limited conversation to collaborators Jun 19, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Working as Intended The behavior described is the intended behavior; this is not a bug
Projects
None yet
Development

No branches or pull requests

4 participants