4

Similarlly to how you can infer function parameters with Typescript via type inference:

type FunctionProps<T> = T extends (arg1: infer U) => any ? U : never;

const stringFunc: (str: string) => string = (str: string): string => str;

type StringFuncType = FunctionProps<typeof stringFunc>;

const a: StringFuncType = 'a';

I want to infer constructor parameters the same way, yet have been unsuccessful so far. Currently my setup looks like this:

type ConstructorProps<T> = T extends {
  new (arg1: infer U): T;
} ? U : never;

class Foo { constructor(a: string) {  } }

type FooConstructor = ConstructorProps<typeof Foo>;

// FooConstructor is always never but should be type string.
const a: FooConstructor = 'a' 

Wasn't sure if this was yet supported in Typescript as the "Advanced Types" section in the TS docs only mention functions and not classes for inference (in regards to parameters).

Anybody else find a solution to this?

4 Answers 4

4

Typescript has a built in utility type for this ConstructorParameters<Type>

https://www.typescriptlang.org/docs/handbook/utility-types.html#constructorparameterstype

Sign up to request clarification or add additional context in comments.

Comments

3

If I change the T to any in the return type of the constructor function, the example works:

type ConstructorProps<T> = T extends {
  new (arg1: infer U): any;
//                     ^^^
} ? U : never;

Remember, T is the type of the constructor function, which is not the same as the type of the constructed object.

2 Comments

This doesn't work. It always infers to never. I'm using typescript v3.5.3. Please provide a typescript playground example, here is proof that it doesn't work. typescriptlang.org/play/…
@Mist Pass typeof Test instead of just Test typescriptlang.org/play?#code/…
0
class Test {
    constructor(foo: number, baz: string) {}
}

type FirstConstructorProp<T> = T extends {
  new (first: infer U, ...rest: any[]): any;
} ? U : never;

type F1 = FirstConstructorProp<Test>; // never
type F2 = FirstConstructorProp<typeof Test>; // number

type ConstructorProps<T> = T extends {
  new (...args: infer U): any;
} ? U : never;

type P1 = ConstructorProps<Test>; // never
type P2 = ConstructorProps<typeof Test>; // [number, string]

Comments

0

It works if you don't use curly brackets, see this other SO.

type ConstructorArgs<T> = T extends new(...args: infer U) => any ? U : never;

class Foo {
    constructor(foo: string, bar: number) { }
}

type Bar = ConstructorArgs<typeof Foo> // type Bar = [string, number]

See associated playground

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.