Closed
Description
TypeScript Version: nightly (2.1.0-dev.20160906)
Code
// (A) declare Wrapper class directly - THIS DOESN'T WORK
// The errors below are all 'TS1092: Type parameters cannot appear on a constructor declaration'
declare class Wrapper {
constructor<TR>(wrapped: () => TR): NullaryWrapper<TR>; // ERROR
constructor<TR, T0>(wrapped: ($0: T0) => TR): UnaryWrapper<TR, T0>; // ERROR
constructor<TR, T0, T1>(wrapped: ($0: T0, $1: T1) => TR): BinaryWrapper<TR, T0, T1>; // ERROR
invoke(...args: any[]): any;
}
// (B) declare Wrapper as static side + instance side interfaces - THIS WORKS FINE
// This is equivalent to the class declaration in (A), but in this case it works without errors.
declare let WrapperConstructor: {
new<TR>(wrapped: () => TR): NullaryWrapper<TR>;
new<TR, T0>(wrapped: ($0: T0) => TR): UnaryWrapper<TR, T0>;
new<TR, T0, T1>(wrapped: ($0: T0, $1: T1) => TR): BinaryWrapper<TR, T0, T1>;
}
// Some strongly-typed versions of the Wrapper shape for specific arities
interface NullaryWrapper<TR> extends Wrapper { invoke(): TR; }
interface UnaryWrapper<TR, T0> extends Wrapper { invoke($0: T0): TR; }
interface BinaryWrapper<TR, T0, T1> extends Wrapper { invoke($0: T0, $1: T1): TR; }
// Some functions to be wrapped
const f0 = () => 42;
const f1 = (s: string) => 42;
const f2 = (s: string, n: number) => 42;
// Create some wrappers using the Wrapper class - DOESN'T WORK
new Wrapper(f0).invoke; // ERROR
new Wrapper(f1).invoke; // ERROR
new Wrapper(f2).invoke; // ERROR
// Create some wrappers using the WrapperConstructor var/interface - WORKS NICELY
new WrapperConstructor(f0).invoke; // () => number
new WrapperConstructor(f1).invoke; // ($0: string) => number
new WrapperConstructor(f2).invoke; // ($0: string, $1: number) => number
I'm trying to infer a strongly-typed shape for the class instance from the arguments passed to the constructor. There is no runtime shenanigans, this is purely for improved type-checking.
Are the TS1092
errors in the code at (A) above really necessary, given that the equivalent code at (B) works fine? I'd rather be able to write the Wrapper
class directly than use the WrapperConstructor
workaround of a var/interface combination.
They do appear to be equivalent typewise, but the (B) version seems a bit hacky. And if the compiler can accept (B), couldn't it also allow (A)?
Or is there a better way to do what I'm trying to do here?