Typescript覆盖Mixin中的构造函数参数



在我当前的typescript项目中,我试图创建一个mixin,这样我就可以创建从不同基类继承的多个子类。

这一切都很好,但我似乎不知道如何告诉typescript新派生类与基类有不同的参数。这里有一个例子,说明了我在这里尝试做什么

interface ConstructorFoo {
bar: string,
}
class Foo {
public bar: string
constructor({ bar }: ConstructorFoo) {
this.bar = bar
}
}
interface ConstructorBaz extends ConstructorFoo {
qux: string
}
type FooType = new (...args: any[]) => Foo
const quxMixin = <T extends FooType>(base: T) => {
return class Baz extends base {
public qux: string
constructor (...args: any[]) {
super(...args)
const { qux } = args[0] as ConstructorBaz
this.qux = qux
}
}
}
const FooBaz = quxMixin(Foo)

const q = new FooBaz({
bar: '1',
qux: '2'  // Argument of type '{ bar: string; qux: string; }' is not assignable to parameter of type 'ConstructorFoo'.
// Object literal may only specify known properties, and 'qux' does not exist in type 'ConstructorFoo'.
})

但我得到了以下错误,因为我不知道如何指定class Baz具有不同的参数类型:

Argument of type '{ bar: string; qux: string; }' is not assignable to parameter of type 'ConstructorFoo'.
Object literal may only specify known properties, and 'qux' does not exist in type 'ConstructorFoo'.

谢谢你的帮助,这里有一个操场链接,详细说明了我想做什么

试试这个:

/** A constructor that constructs a T using the arguments A */
type Constructor<T, A extends unknown[]> = new (...args: A) => T
/** Exclude the first element of an array */
type Tail<T extends readonly unknown[]> = T extends [unknown, ...infer U] ? U : never
interface Qux {
qux: string
}
/** Add the Qux type to the first item in an array */
// If the T is empty, T[0] will be never and T[0] & Qux will also be never, so
// this needs to check if the array is empty
type AddQux<T extends unknown[]> = T extends [] ? [Qux] : [T[0] & Qux, ...Tail<T>]
// quxMixin accepts a constructor base and returns another constructor
const quxMixin = <C extends Constructor<any, any[]>>(base: C): Constructor<
// that constructs the original class with the qux property
InstanceType<C> & Qux,
// using the same arguments as the original constructor except that the first
// parameter includes the qux property
AddQux<ConstructorParameters<C>>
> => {
return class Baz extends base {
public qux: string
// args must be any[] due to https://github.com/microsoft/TypeScript/issues/37142
constructor (...args: any[]) {
super(...args)
const { qux } = args[0] as Qux
this.qux = qux
}
}
}
const FooBaz = quxMixin(Foo)
const q = new FooBaz({ bar: '1', qux: '2' })
q.qux // string

这使用实用程序类型InstanceTypeConstructorParameters:

/** Obtain the return type of a constructor function type */
type InstanceType<T extends new (...args: any) => any> = T extends new (...args: any) => infer R ? R : any
/** Obtain the parameters of a constructor function type in a tuple */
type ConstructorParameters<T extends new (...args: any) => any> = T extends new (...args: infer P) => any ? P : never

游乐场链接

最新更新