#How to get all class constructor parameters type as tuple union

7 messages · Page 1 of 1 (latest)

rain thornBOT
#
kennarddh#0

Preview:```ts
class X {
constructor(arg1: number, arg2: string)
constructor(arg1: string)
constructor(obj: string | number, arg2?: string) {}
}

type ConstructorsParameters<T> = T

type Y = ConstructorsParameters<X>

type ExpectedY = [number, string] | [string]```

fair rock
#

@twilit swan I don't think it's possible, condtional type-based utilities (such as ConstructorParameters) don't really work with overloads - they pick the last overload which is intended to be the most general.

#

You could write you class with a union of arguments, instead of overloads, though.

rain thornBOT
#
class X {
    constructor(...args: [string] | [number, string]) {}   
}

type Y = ConstructorParameters<typeof X>
//   ^? - type Y = [string] | [number, string]
cobalt swan
#

have to agree with retsam here, you can’t spread over overloads

sick leaf
#

TS can't infer an arbitrary amount of overloads, best you can do is this

class X {
  constructor(arg1: number, arg2: string)
  constructor(arg1: string)
  constructor(obj: string | number, arg2?: string) {}
}

type ConstructorsParameters<T> = T extends {
    new(...args: infer A1): unknown
    new(...args: infer A2): unknown
} ? A1 | A2 : never

type Y = ConstructorsParameters<typeof X>

Then you can chain these to work with a variable number of overloads:

// Infers up to 3 last constructor signatures
type ConstructorsParameters<T> = T extends {
    new(...args: infer A1): unknown
    new(...args: infer A2): unknown
    new(...args: infer A3): unknown
} ? A1 | A2 | A3 : T extends {
    new(...args: infer A1): unknown
    new(...args: infer A2): unknown
} ? A1 | A2 : T extends {
    new(...args: infer A1): unknown
} ? A1 : never

This can be extended to work with a reasonable amount of overloads your constructors can have

rain thornBOT
#
kennarddh#0

Preview:```ts
class X {
constructor(arg1: number, arg2: string)
constructor(arg1: string)
constructor(obj: string | number, arg2?: string) {}
}

type ConstructorsParameters<T> = T extends {
new (...args: infer A1): unknown
new (...args: infer A2): unknown
}
? A1 | A2
: never
...```