-
Notifications
You must be signed in to change notification settings - Fork 8
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Objection v2.x is out, would it be possible to add TypeScript definitions for this plugin? #12
Comments
I've been trying this out and it's looking promising. I want to make sure I can get typings working with other mixins, and determine backward compatibility before making a release. By following the discussion here, just rewriting everything in TypeScript and getting (seemingly) proper types for custom query builder was relatively easy. I, however, needed to generate declaration files while transpiling the source to JS (so that it can be used in JS projects), which was giving me trouble to no end. Here's a minimal example of a plugin with a custom query builder: type AnyConstructor<A = object> = new (...input: any[]) => A;
export function Mixin(options: {sessionKey: string}) {
return function <T extends AnyConstructor<Model>>(Base: T) {
class MyQueryBuilder<M extends Model, R = M[]> extends QueryBuilder<M, R> {
public ArrayQueryBuilderType!: MyQueryBuilder<M, M[]>;
public SingleQueryBuilderType!: MyQueryBuilder<M, M>;
public NumberQueryBuilderType!: MyQueryBuilder<M, number>;
public PageQueryBuilderType!: MyQueryBuilder<M, Page<M>>;
public session(session: any) {
return this.mergeContext({
[options.sessionKey]: session
});
}
}
return class extends Base {
public static QueryBuilder = MyQueryBuilder;
public QueryBuilderType!: MyQueryBuilder<this, this[]>;
};
};
} First thing that's important to note is that
This error is basically telling me that I must export type AnyConstructor<A = object> = new (...input: any[]) => A;
interface MyQueryBuilder<M extends Model, R = M[]> extends QueryBuilder<M, R> {
ArrayQueryBuilderType: CursorQueryBuilder<M, M[]>;
SingleQueryBuilderType: CursorQueryBuilder<M, M>;
NumberQueryBuilderType: CursorQueryBuilder<M, number>;
PageQueryBuilderType: CursorQueryBuilder<M, Page<M>>;
session(): this;
}
interface MyModelInstance<M extends Model> {
QueryBuilderType: MyQueryBuilder<this & M, this[]>;
}
interface MyModelStatic<M extends Model> {
QueryBuilder: any; // Not sure what this does
new (...args: any[]): MyModelInstance<M> & M;
}
export function Mixin(options: {sessionKey: string}) {
return function <T extends AnyConstructor<Model>>(Base: T): MyModelStatic<InstanceType<T>> & T {
class MyQueryBuilder<M extends Model, R = M[]> extends QueryBuilder<M, R> {
public ArrayQueryBuilderType!: MyQueryBuilder<M, M[]>;
public SingleQueryBuilderType!: MyQueryBuilder<M, M>;
public NumberQueryBuilderType!: MyQueryBuilder<M, number>;
public PageQueryBuilderType!: MyQueryBuilder<M, Page<M>>;
public session(session: any) {
return this.mergeContext({
[options.sessionKey]: session
});
}
}
class MyModel extends Base {
public static QueryBuilder = MyQueryBuilder;
public QueryBuilderType!: MyQueryBuilder<this, this[]>;
}
return MyModel as MyModelStatic<InstanceType<T>> & T;
};
} With my limited testing, everything seems to be working as expected as far as typings go (TS v3.7.3). The TS rewrite is in the |
I was able to extract class MyQueryBuilder<M extends Model, R = M[]> extends QueryBuilder<M, R> {
public ArrayQueryBuilderType!: MyQueryBuilder<M, M[]>;
public SingleQueryBuilderType!: MyQueryBuilder<M, M>;
public NumberQueryBuilderType!: MyQueryBuilder<M, number>;
public PageQueryBuilderType!: MyQueryBuilder<M, Page<M>>;
public session(session: any) {
return this.mergeContext({
[this.options().sessionKey]: session
});
}
private options() {
const cls = this.modelClass() as any;
return cls.options as Options;
}
}
type ModelConstructor = new (...input: any[]) => Model;
interface MyModelInstance<T extends ModelConstructor > {
/* MyQueryBuilder<this, this[]> would be optimal, but not possible since `this`
* doesn't extend Model. Not sure what this affects either.
*/
QueryBuilderType: MyQueryBuilder<this & InstanceType<T>, this[]>;
}
interface MyModel<T extends ModelConstructor> {
options: Options;
QueryBuilder: typeof CursorQueryBuilder;
new (...args: any[]): MyModelInstance<T> & T;
}
export type MyMixin<T extends ModelConstructor> = MyModel<T> & T;
export function mixin(options: {sessionKey: string}) {
return function <T extends ModelConstructor>(Base: T) {
return class extends Base {
// This let's us move MyQueryBuilder outside the function
public static options = options;
public static QueryBuilder = MyQueryBuilder;
public QueryBuilderType!: MyQueryBuilder<this, this[]>;
} as MyMixin<T>;
};
} I'm still required to write explicit types for |
To me it seems like typings are still impossible to write. It's close, but breaks down once you use multiple plugins that modify the query builder. |
Related to #1
The text was updated successfully, but these errors were encountered: