Typescript 返回具有静态属性的类的构造函数签名
作为我昨天的后续:我现在有了一个基于参数返回类的函数Typescript 返回具有静态属性的类的构造函数签名,typescript,Typescript,作为我昨天的后续:我现在有了一个基于参数返回类的函数 function Model<T>(name: string, defaults: () => T) : new(options: Partial<T>) => Pick<T, keyof T> { return class { public _symbol = name protected options: T constructor
function Model<T>(name: string, defaults: () => T) : new(options: Partial<T>) => Pick<T, keyof T> {
return class {
public _symbol = name
protected options: T
constructor (options: Partial<T>) {
this.options = { ...defaults(), ...options }
return new Proxy(this, {
get (target, prop: keyof T) {
return target.options[prop]
}
})
}
} as any
}
type Options {
username: string,
email: string
}
class User extends Model<Options>('user', () => ({
username: getRandomUsername(),
email: getRandomEmail()
}) {
sayHello () : void {
console.log('Hello ' + this.options.username)
}
}
这样,新的User.\u符号编译并返回User。但是,我不希望_symbol是一个实例属性,我希望它是一个静态类属性。不幸的是,我找不到任何关于如何修改此新类型ModelClass以指定具有静态属性的类的信息。在TypeScript中有什么方法可以解决这个问题吗?有点没有答案:让TS自动解析类型
function Model<T>(name: string, defaults: () => T) // Drop return type annotation
{
return class
{
// Change this to public static
public static _symbol = name
protected options: T
constructor(options: Partial<T>)
{
this.options = { ...defaults(), ...options }
}
} // Drop as cast
}
如前所述,由于返回的代理,这无法正常工作。除非除了返回传入/默认值之外,您还需要代理,否则可以通过直接将所有属性放在某个对象实例上并返回该实例来消除代理 下面是将类转换为工厂函数的示例:
export function createModel<T, E extends T>(
name: string,
defaults: () => E
)
{
const factory = (options: Partial<T>) =>
{
return { ...defaults(), ...options };
}
factory._symbol = name;
return factory;
}
这似乎是一个合理的想法,但由于导出的类表达式的属性“options”可能不是私有的或受保护的,所以它无法编译。即使选项被标记为受保护。此外,我还需要将某些函数注释为返回继承此模型的类的对象,我很确定我仍然需要正确的类型注释。哦,这似乎是我导出该函数的默认值时得出的。@Padarom:但我想知道为什么会有这样的问题。因此,如果我将选项公开,它会编译。但是,它没有正确地推断类型,尽管这是因为我最初没有在问题中指定类型被拾取的原因,但我将问题编辑为clarify@Padarom:这首先不起作用,因为您不能从构造函数返回与构造的类实例不同的对象。如果要返回代理,请不要返回类,而是返回一个工厂函数,该工厂函数构造实例,但只向其返回代理。当然,您将不再能够在常规继承中使用它。
export function createModel<T, E extends T>(
name: string,
defaults: () => E
)
{
const factory = (options: Partial<T>) =>
{
return { ...defaults(), ...options };
}
factory._symbol = name;
return factory;
}
type UserOptions = {
username: string,
email: string
}
type User = UserOptions & {
sayHello(): void;
}
const userFactory = createModel<UserOptions, User>(
'user',
() => ({
username: 'a',
email: 'b',
sayHello(): void
{
console.log('Hello ' + this.username)
}
})
);
const steve = userFactory({ username: 'steve' });
console.log(steve.username);
steve.sayHello();