Hopefully this one can get fixed quickly since it is a pretty major regression. I spent a lot of time figuring out exactly which version range is causing the failure as well as trying to figure out a minimal test case.
TypeScript Version:
Failure at version: 3.6.0-dev.20190807 and above.
Everything works: 3.6.0-dev.20190806 and lower.
Code
To run:
yarn
./node_modules/.bin/tsc
Expected behavior:
No error.
Actual behavior:
tsc-fail/node_modules/typescript/lib/tsc.js:75299
throw e;
^
RangeError: Maximum call stack size exceeded
at Object.getObjectFlags (tsc-fail/node_modules/typescript/lib/tsc.js:10227:28)
at isExcessPropertyCheckTarget (tsc-fail/node_modules/typescript/lib/tsc.js:42328:51)
at Object.every (tsc-fail/node_modules/typescript/lib/tsc.js:295:22)
at isExcessPropertyCheckTarget (tsc-fail/node_modules/typescript/lib/tsc.js:42331:44)
at isKnownProperty (tsc-fail/node_modules/typescript/lib/tsc.js:42317:52)
at hasCommonProperties (tsc-fail/node_modules/typescript/lib/tsc.js:37523:21)
at isRelatedTo (tsc-fail/node_modules/typescript/lib/tsc.js:36276:58)
at typeRelatedToSomeType (tsc-fail/node_modules/typescript/lib/tsc.js:36458:35)
at isRelatedTo (tsc-fail/node_modules/typescript/lib/tsc.js:36300:34)
at isPropertySymbolTypeRelated (tsc-fail/node_modules/typescript/lib/tsc.js:37137:28)
Maybe related: #32582
Running with 3.6.3 the error has changed a bit...
RangeError: Maximum call stack size exceeded
at recursiveTypeRelatedTo (/node_modules/typescript/lib/tsc.js:36800:44)
at isRelatedTo (/node_modules/typescript/lib/tsc.js:36477:38)
at typeRelatedToSomeType (/node_modules/typescript/lib/tsc.js:36614:35)
at isRelatedTo (/node_modules/typescript/lib/tsc.js:36456:34)
at eachTypeRelatedToType (/node_modules/typescript/lib/tsc.js:36736:35)
at isRelatedTo (/node_modules/typescript/lib/tsc.js:36452:25)
at isPropertySymbolTypeRelated (/node_modules/typescript/lib/tsc.js:37293:28)
at propertyRelatedTo (/node_modules/typescript/lib/tsc.js:37333:31)
at propertiesRelatedTo (/node_modules/typescript/lib/tsc.js:37434:43)
at isRelatedTo (/node_modules/typescript/lib/tsc.js:36468:34)
Version 3.7.0-dev.20190917
/node_modules/typescript/lib/tsc.js:75802
throw e;
^
RangeError: Maximum call stack size exceeded
at isUnconstrainedTypeParameter (/node_modules/typescript/lib/tsc.js:37850:46)
at /node_modules/typescript/lib/tsc.js:37854:105
at Object.some (/node_modules/typescript/lib/tsc.js:673:25)
at isTypeReferenceWithGenericArguments (/node_modules/typescript/lib/tsc.js:37854:58)
at getRelationKey (/node_modules/typescript/lib/tsc.js:37884:17)
at recursiveTypeRelatedTo (/node_modules/typescript/lib/tsc.js:36895:26)
at isRelatedTo (/node_modules/typescript/lib/tsc.js:36568:38)
at eachTypeRelatedToType (/node_modules/typescript/lib/tsc.js:36827:35)
at isRelatedTo (/node_modules/typescript/lib/tsc.js:36543:25)
at isPropertySymbolTypeRelated (/node_modules/typescript/lib/tsc.js:37393:28)
This also happens with objection.js typings. I don't know if this helps, but you can reproduce it like this:
git clone [email protected]:Vincit/objection.js.git
git checkout typescript-issue-33460
npm install
npm install [email protected]
npm run test-typings
Using the package.json version 3.5.3 works
npm install [email protected]
npm run test-typings
I was able to find out that this monstrosity of a type is the culprit:
Oh, the original reproduction was also done using objection typings :smile:
@koskimas I'm also sorry to say that I've now moved on from Objection to MikroORM. =(
I just found out that changing this
type GraphParameters = {
'#dbRef'?: MaybeCompositeId;
'#ref'?: string;
'#id'?: string;
};
type PartialModelGraph<T> = {
[K in NonFunctionPropertyNames<T>]?: Exclude<T[K], undefined> extends Model
? PartialModelGraph<Exclude<T[K], undefined>>
: Exclude<T[K], undefined> extends Array<infer I>
? (I extends Model ? PartialModelGraph<I>[] : (T[K] | NonPrimitiveValue))
: (T[K] | NonPrimitiveValue);
} &
GraphParameters;
into this
type GraphParameters = {
'#dbRef'?: MaybeCompositeId;
'#ref'?: string;
'#id'?: string;
};
type PartialModelGraph<M, T = M & GraphParameters> = {
[K in NonFunctionPropertyNames<T>]?: Exclude<T[K], undefined> extends Model
? PartialModelGraph<Exclude<T[K], undefined>>
: Exclude<T[K], undefined> extends Array<infer I>
? (I extends Model ? PartialModelGraph<I>[] : (T[K] | NonPrimitiveValue))
: (T[K] | NonPrimitiveValue);
}
fixes the problem.
Also note that @lookfirst's reproduction uses objection 1.6.9 while the above types and my repro is with objection 2.0 typings which have been completely rewritten from scratch. So this fix only applies to my repro.
I just ran into the same problem on v3.7.2
RangeError: Maximum call stack size exceeded
at isRelatedTo (node_modules\typescript\lib\tsc.js:1:1)
at typeRelatedToSomeType (node_modules\typescript\lib\tsc.js:38604:35)
at isRelatedTo (node_modules\typescript\lib\tsc.js:38438:34)
at eachTypeRelatedToType (node_modules\typescript\lib\tsc.js:38726:35)
at isRelatedTo (node_modules\typescript\lib\tsc.js:38434:25)
at isPropertySymbolTypeRelated (node_modules\typescript\lib\tsc.js:39293:28)
at propertyRelatedTo (node_modules\typescript\lib\tsc.js:39333:31)
at propertiesRelatedTo (node_modules\typescript\lib\tsc.js:39437:43)
at isRelatedTo (node_modules\typescript\lib\tsc.js:38450:34)
at typeRelatedToSomeType (node_modules\typescript\lib\tsc.js:38604:35)
The problem appeared when using "morphism" together with "sequelize" and I managed to reproduce it with this:
(sorry, it's still a bit lengthy)
function morphism<TSchema = Schema<DestinationFromSchema<Schema>, SourceFromSchema<Schema>>, Source extends SourceFromSchema<TSchema> = SourceFromSchema<TSchema>>(schema: TSchema, data: Source[]): DestinationFromSchema<TSchema>[] {
throw new Error();
}
type SourceFromSchema<T> = T extends Schema<unknown, infer U> ? U : never;
type DestinationFromSchema<T> = T extends Schema<infer U> ? U : never;
declare const SCHEMA_OPTIONS_SYMBOL: unique symbol;
type Schema<Target = any, Source = any> = {
[destinationProperty in keyof Target]?: Schema<Target[destinationProperty], Source>;
} & {
[SCHEMA_OPTIONS_SYMBOL]?: any;
};
export class Sequelize {
public Sequelize!: typeof Sequelize;
}
interface MyModel extends Sequelize {
vehicleId: string;
}
export interface MyModelDTO {
id: string;
}
export const MyModelDTOVehicleModel: Schema<MyModel, MyModelDTO> = {
vehicleId: 'id',
};
const output: MyModel[] = morphism(MyModelDTOVehicleModel, [{
id: 'ID',
}]);
As mentioned before it works in version 3.5.3.
Just use MikroORM v3, seriously.
Spent this morning looking into this:
getUnmatchedProperties doesn't seem to show in any stack traces (likely because it's a generator func which is transpile out) but it's where a lot of the looping goes throughThe loop seems to roughly be (based on getUnmatchedProperties):
R -> PIntersection|IncludesNonWideningType with R -> P as'{ '#id'?: string; '#ref'?: never; '#dbRef'?: never }' and{ [P in NonFunctionPropertyNames<T>]?: DeepPartialGraph<T[P]> } in the targetR ('Object') -> R ('Intersection|IncludesNonWideningType')P (Object) -> P (Intersection|IncludesNonWideningType)R -> P againI've not been able to replicate this in a baseline yet
Current baseline WIP
// R -> Model
//
// @target: ES2019
// @strict
export interface Constructor
new (...args: any[]): M;
}
export interface QueryBuilderYieldingOne
export interface QueryBuilderYieldingOneOrNone
export interface QueryBuilderYieldingCount
Executable
throwIfNotFound(): this;
}
type Value =
| string
| number
| boolean
| Date
| string[]
| number[]
| boolean[]
| Date[]
| null
| Raw
| Literal;
export interface Page
total: number;
results: QM[];
}
interface BluebirdMapper
(item: T, index: number): Result;
}
interface NodeStyleCallback {
(err: any, result?: any): void;
}
interface InsertGraph
(modelsOrObjects?: DeepPartialGraph
(): this;
}
interface QueryBuilderBase
modify(func: (builder: this) => void): this;
modify(namedFilter: string): this;
applyFilter(...namedFilters: string[]): this;
// findById(id: Id): QueryBuilderYieldingOneOrNone
// findById(idOrIds: IdOrIds): this;
// findByIds(ids: Id[] | Id[][]): this;
// /** findOne is shorthand for .where(...whereArgs).first() */
// findOne: FindOne
// insert: Insert insertGraph: InsertGraph // /** // /** // /** // upsertGraph: UpsertGraph // /** // relate // forUpdate(): this; // // TODO: fromJS does not exist in current knex documentation: http://knexjs.org/#Builder-fromJS // joinRelation: JoinRelation; // // TODO: avgDistinct does not exist in current knex documentation: http://knexjs.org/#Builder-fromJS // // TODO: the return value of this method matches the knex typescript and documentation. // whereComposite(column: ColumnRef, value: Value | QueryBuilder // whereJsonSupersetOf: WhereJson // whereJsonNotSupersetOf: WhereJson // whereJsonSubsetOf: WhereJson // whereJsonNotSubsetOf: WhereJson // whereJsonIsArray: WhereFieldExpression // whereJsonNotArray: WhereFieldExpression // whereJsonIsObject: WhereFieldExpression // whereJsonNotObject: WhereFieldExpression // whereJsonHasAny: WhereJsonExpression // whereJsonHasAll: WhereJsonExpression // Non-query methods: context(queryContext: object): this; reject(reason: any): this; isExecutable(): boolean; runBefore(fn: (result: any, builder: QueryBuilder //eagerAlgorithm(algo: EagerAlgorithm): this; // eager(relationExpression: RelationExpression, filters?: FilterExpression // joinEager(relationExpression: RelationExpression, filters?: FilterExpression // naiveEager(relationExpression: RelationExpression, filters?: FilterExpression // allowEager: RelationExpressionMethod // allowInsert: RelationExpressionMethod modelClass(): typeof Model; toString(): string; toSql(): string; skipUndefined(): this; transacting(transaction: Transaction): this; clone(): this; // We get map asCallback(callback: NodeStyleCallback): Promise nodeify(callback: NodeStyleCallback): Promise resultSize(): Promise page(page: number, pageSize: number): QueryBuilder // alias(alias: string): this; //traverse(modelClass: typeof Model, traverser: TraverserFunction): this; pick(modelClass: typeof Model, properties: string[]): this; omit(modelClass: typeof Model, properties: string[]): this; returning(columns: string | string[]): QueryBuilder // timeout(ms: number, options?: TimeoutOptions): this; export interface Executable export interface QueryBuilder interface Transaction { interface QueryInterface // Joins // Withs // Wheres // Group by // Order by // Union // Having // Clear // Paging // Aggregation debug(enabled?: boolean): this; //del(): QueryBuilderYieldingCount transacting(trx: Transaction): this; clone(): this; interface Castable { export interface Literal extends Castable {} export interface Reference extends Castable {} type Raw = any; interface As interface Select interface Table interface Distinct interface Join type ColumnRef = string | Raw | Reference | QueryBuilder interface JoinRaw interface With interface WithRaw interface WithWrapped interface Where ; interface FindOne interface WhereRaw interface WhereWrapped interface WhereNull interface WhereIn interface WhereBetween interface WhereExists interface GroupBy interface OrderBy interface SetOperations ; // commons interface ColumnNamesMethod interface RawMethod // TS 2.5 doesn't support interfaces with static methods or fields, so // static raw: knex.RawBuilder; // static BelongsToOneRelation: Relation; // static JoinEagerAlgorithm: EagerAlgorithm; // static getRelations(): { [key: string]: Relation }; static query // // This can only be used as a subquery so the result model type is irrelevant. // // fromJson and fromDatabaseJson both return an instance of Model, not a Model class: // static omitImpl(f: (obj: object, prop: string) => void): void; // // loadRelated is overloaded to support both Model and Model[] variants: // static loadRelated // static traverse( // static traverse(models: Model | Model[], traverser: TraverserFunction): void; // static tableMetadata(opt?: TableMetadataOptions): TableMetadata; // $id(): any; // $beforeValidate(jsonSchema: JsonSchema, json: Pojo, opt: ModelOptions): JsonSchema; // $toDatabaseJson(): object; // $set // $query // /** // /** // $loadRelated // $traverse(traverser: TraverserFunction): void; // $knex(): knex; // $beforeInsert(queryContext: QueryContext): Promise type GraphModel type NonFunctionPropertyNames interface DeepPartialGraphArray type DeepPartialGraphModel type DeepPartialGraph export interface InsertGraphOptions { export interface QueryContext { export interface TableMetadata { export interface TableMetadataOptions { export interface FetchTableMetadataOptions { class R extends Model { export class P extends Model { export class D extends Model { async function main() { main().then(() => {
// insertAndFetch(modelOrObject: Partial
// insertAndFetch(modelsOrObjects?: Partial
// insertGraphAndFetch: InsertGraphAndFetch
// * insertWithRelated is an alias for insertGraph.
// */
// insertWithRelated: InsertGraph
// insertWithRelatedAndFetch: InsertGraphAndFetch
// * @return a Promise of the number of updated rows
// */
// update(modelOrObject: PartialUpdate
// updateAndFetch(modelOrObject: PartialUpdate
// updateAndFetchById(id: Id, modelOrObject: PartialUpdate
// * @return a Promise of the number of patched rows
// */
// patch(modelOrObject: PartialUpdate
// patchAndFetchById(idOrIds: IdOrIds, modelOrObject: PartialUpdate
// patchAndFetch(modelOrObject: PartialUpdate
// upsertGraphAndFetch: UpsertGraphAndFetch
// * @return a Promise of the number of deleted rows
// */
// deleteById(idOrIds: IdOrIds): QueryBuilderYieldingCount
// unrelate(): this;
// forShare(): this;
// withSchema(schemaName: string): this;
// innerJoinRelation: JoinRelation;
// outerJoinRelation: JoinRelation;
// leftJoinRelation: JoinRelation;
// leftOuterJoinRelation: JoinRelation;
// rightJoinRelation: JoinRelation;
// rightOuterJoinRelation: JoinRelation;
// fullOuterJoinRelation: JoinRelation;
// // TODO: modify does not exist in current knex documentation: http://knexjs.org/#Builder-modify
// // The Objection documentation incorrectly states this returns a QueryBuilder.
// columnInfo(column?: string): Promise
// column: ColumnRef,
// operator: string,
// value: Value | QueryBuilder
// whereComposite(
// column: ColumnRef[],
// operator: string,
// value: Value[] | QueryBuilder
// whereInComposite(column: ColumnRef | ColumnRef[], values: Value[] | QueryBuilder
// orWhereJsonSupersetOf: WhereJson
// orWhereJsonNotSupersetOf: WhereJson
// orWhereJsonSubsetOf: WhereJson
// orWhereJsonNotSubsetOf: WhereJson
// orWhereJsonIsArray: WhereFieldExpression
// orWhereJsonNotArray: WhereFieldExpression
// orWhereJsonIsObject: WhereFieldExpression
// orWhereJsonNotObject: WhereFieldExpression
// orWhereJsonHasAny: WhereJsonExpression
// orWhereJsonHasAll: WhereJsonExpression
context(): QueryContext;
mergeContext(queryContext: object): this;
resolve(value: any): this;
isFind(): boolean;
isInsert(): boolean;
isUpdate(): boolean;
isDelete(): boolean;
isRelate(): boolean;
isUnrelate(): boolean;
hasWheres(): boolean;
hasSelects(): boolean;
hasEager(): boolean;
runAfter(fn: (result: any, builder: QueryBuilder
onBuild(fn: (builder: this) => void): this;
//onBuildKnex(fn: (knexBuilder: knex.QueryBuilder, builder: this) => void): this;
onError(fn: (error: Error, builder: this) => any): this;
// eagerOptions(opts: EagerOptions): this;
// mergeEager(relationExpression: RelationExpression, filters?: FilterExpression
// mergeJoinEager(relationExpression: RelationExpression, filters?: FilterExpression
// mergeNaiveEager(relationExpression: RelationExpression, filters?: FilterExpression
// modifyEager: ModifyEager
// filterEager: ModifyEager
// allowUpsert: RelationExpressionMethodthen and catch by extending Promise
bind(context: any): Promise
reflect(): Promise
// range(): QueryBuilder
range(start: number, end: number): QueryBuilder
pluck(propertyName: string): this;
// first(): QueryBuilderYieldingOneOrNone
// aliasFor(modelClassOrTableName: string | ModelClass
// tableRefFor(modelClass: ModelClass
// tableNameFor(modelClass: ModelClass
pick(properties: string[]): this;
omit(properties: string[]): this;
}
execute(): Promise
}
extends QueryBuilderBase
Executable
throwIfNotFound(): QueryBuilder
castTo
}
savepoint(transactionScope: (trx: Transaction) => any): Promise
commit
rollback
}
select: Select
as: As
columns: Select
column: Select
from: Table
into: Table
table: Table
distinct: Distinct
join: Join
joinRaw: JoinRaw
innerJoin: Join
leftJoin: Join
leftOuterJoin: Join
rightJoin: Join
rightOuterJoin: Join
outerJoin: Join
fullOuterJoin: Join
crossJoin: Join
with: With
withRaw: WithRaw
withWrapped: WithWrapped
where: Where
andWhere: Where
orWhere: Where
whereNot: Where
andWhereNot: Where
orWhereNot: Where
whereRaw: WhereRaw
orWhereRaw: WhereRaw
andWhereRaw: WhereRaw
whereWrapped: WhereWrapped
havingWrapped: WhereWrapped
whereExists: WhereExists
orWhereExists: WhereExists
whereNotExists: WhereExists
orWhereNotExists: WhereExists
whereIn: WhereIn
orWhereIn: WhereIn
whereNotIn: WhereIn
orWhereNotIn: WhereIn
whereNull: WhereNull
orWhereNull: WhereNull
whereNotNull: WhereNull
orWhereNotNull: WhereNull
whereBetween: WhereBetween
orWhereBetween: WhereBetween
andWhereBetween: WhereBetween
whereNotBetween: WhereBetween
orWhereNotBetween: WhereBetween
andWhereNotBetween: WhereBetween
whereColumn: Where
andWhereColumn: Where
orWhereColumn: Where
whereNotColumn: Where
andWhereNotColumn: Where
orWhereNotColumn: Where
groupBy: GroupBy
groupByRaw: RawMethod
orderBy: OrderBy
orderByRaw: RawMethod
union: SetOperations
unionAll: SetOperations
intersect: SetOperations
having: Where
andHaving: Where
orHaving: Where
havingRaw: WhereRaw
orHavingRaw: WhereRaw
havingIn: WhereIn
orHavingIn: WhereIn
havingNotIn: WhereIn
orHavingNotIn: WhereIn
havingNull: WhereNull
orHavingNull: WhereNull
havingNotNull: WhereNull
orHavingNotNull: WhereNull
havingExists: WhereExists
orHavingExists: WhereExists
havingNotExists: WhereExists
orHavingNotExists: WhereExists
havingBetween: WhereBetween
orHavingBetween: WhereBetween
havingNotBetween: WhereBetween
orHavingNotBetween: WhereBetween
clearSelect(): this;
clearOrder(): this;
clearWhere(): this;
offset(offset: number): this;
limit(limit: number): this;
count(columnName?: string): this;
countDistinct(columnName?: string): this;
min(columnName: string): this;
max(columnName: string): this;
sum(columnName: string): this;
sumDistinct(columnName: string): this;
avg(columnName: string): this;
avgDistinct(columnName: string): this;
increment(columnName: string, amount?: number): this;
decrement(columnName: string, amount?: number): this;
pluck(column: string): this;
//delete(): QueryBuilderYieldingCount
truncate(): this;
connection(connection: any): this;
}
castText(): this;
castInt(): this;
castBigInt(): this;
castFloat(): this;
castDecimal(): this;
castReal(): this;
castBool(): this;
castJson(): this;
castArray(): this;
asArray(): this;
castType(sqlType: string): this;
castTo(sqlType: string): this;
as(alias: string): this;
}
(alias: string): QueryBuilder
}
(tableName: TableName): QueryBuilder
(callback: (this: QueryBuilder
}
(raw: Raw): QueryBuilder
(tableName: TableName, clause: (this: any, join: any) => void): QueryBuilder
(tableName: TableName, columns: { [key: string]: string | number | Raw | Reference }): QueryBuilder
(tableName: TableName, raw: Raw): QueryBuilder
(tableName: TableName, column1: ColumnRef, column2: ColumnRef): QueryBuilder
(tableName: TableName, column1: ColumnRef, operator: string, column2: ColumnRef): QueryBuilder
(queryBuilder: QueryBuilder
}
(sql: string, bindings?: any): QueryBuilder
}
(alias: string, raw: Raw): QueryBuilder
// join: knex.JoinClause;
(alias: string, sql: string, bindings?: any): QueryBuilder
}
(alias: string, callback: (queryBuilder: QueryBuilder
}
(callback: (this: QueryBuilder
(object: object): QueryBuilder
(column: keyof QM | ColumnRef, value: Value | Reference | QueryBuilder
(column: keyof QM | ColumnRef, operator: string, value: Value | Reference | QueryBuilder
RM,
RV
(
column: ColumnRef,
callback: (this: QueryBuilder
}
(condition: boolean): QueryBuilderYieldingOneOrNone
(
callback: (this: QueryBuilder
(object: object): QueryBuilderYieldingOneOrNone
(sql: string, ...bindings: any[]): QueryBuilderYieldingOneOrNone
(sql: string, bindings: any): QueryBuilderYieldingOneOrNone
(column: ColumnRef, value: Value | Reference | QueryBuilder
(
column: ColumnRef,
operator: string,
value: Value | Reference | QueryBuilder
(
column: ColumnRef,
callback: (this: QueryBuilder
}
(condition: boolean): QueryBuilder
}
(callback: (queryBuilder: QueryBuilder
}
(column: ColumnRef): QueryBuilder
}
(column: ColumnRef | ColumnRef[], values: Value[]): QueryBuilder
(
column: ColumnRef | ColumnRef[],
callback: (this: QueryBuilder
(column: ColumnRef | ColumnRef[], query: QueryBuilder
}
(column: ColumnRef, range: [Value, Value]): QueryBuilder
}
(callback: (this: QueryBuilder
(query: QueryBuilder
(raw: Raw): QueryBuilder
}
(column: ColumnRef, direction?: string): QueryBuilder
}
(
callback: (this: QueryBuilder
): QueryBuilder
callbacks: ((this: QueryBuilder
): QueryBuilder
QM[]
}
(...columnNames: ColumnRef[]): QueryBuilder
(columnNames: ColumnRef[]): QueryBuilder
}
(sql: string, ...bindings: any[]): QueryBuilder
(sql: string, bindings: any): QueryBuilder
(raw: Raw): QueryBuilder
}
// this must be declared as a class:
declare class Model {
static tableName: string;
static jsonSchema: any;
static idColumn: string | string[];
static modelPaths: string[];
static relationMappings: any;
static jsonAttributes: string[];
static virtualAttributes: string[];
static uidProp: string;
static uidRefProp: string;
static dbRefProp: string;
static propRefRegex: RegExp;
static pickJsonSchemaProperties: boolean;
static defaultEagerAlgorithm?: any;
static defaultEagerOptions?: any;
// static QueryBuilder: typeof QueryBuilder;
static columnNameMappers: any;
static relatedFindQueryMutates: boolean;
static relatedInsertQueryMutates: boolean;
static modifiers: any;
// static fn: knex.FunctionHelper;
// static HasOneRelation: Relation;
// static HasManyRelation: Relation;
// static ManyToManyRelation: Relation;
// static HasOneThroughRelation: Relation;
// static WhereInEagerAlgorithm: EagerAlgorithm;
// static NaiveEagerAlgorithm: EagerAlgorithm;
this: Constructor
trxOrKnex?: Transaction // | knex
): QueryBuilder
// static relatedQuery(relationName: string): QueryBuilder
// static knexQuery(): knex.QueryBuilder;
// static bindKnex
// static bindTransaction
// static createValidator(): Validator;
// static createValidationError(args: CreateValidationErrorArgs): Error;
// static createNotFoundError(): Error;
// static fromJson
// static fromDatabaseJson
// static loadRelated
// this: Constructor
// models: QM[],
// expression: RelationExpression,
// filters?: Filters
// trxOrKnex?: Transaction | knex
// ): QueryBuilder
// this: Constructor
// model: QM,
// expression: RelationExpression,
// filters?: Filters
// trxOrKnex?: Transaction | knex
// ): QueryBuilderYieldingOne
// filterConstructor: typeof Model,
// models: Model | Model[],
// traverser: TraverserFunction
// ): void;
// static fetchTableMetadata(opt?: FetchTableMetadataOptions): Promise
// // Implementation note: At least as of TypeScript 2.7, subclasses of
// // methods that return this are not compatible with their superclass.
// // For example, class Movie extends Model could not be passed as a
// // "Model" to a function, because the methods that return this return
// // Movie, and not Model. The foo<M>(this: M, ... is a workaround.
// $id(id: any): void;
// $validate(json: Pojo, opt: ModelOptions): Pojo; // may throw ValidationError if validation fails
// $afterValidate(json: Pojo, opt: ModelOptions): void; // may throw ValidationError if validation fails
// $toJson(opt?: ToJsonOptions): object;
// toJSON(opt?: ToJsonOptions): object;
// $parseDatabaseJson(json: Pojo): Pojo;
// $formatDatabaseJson(json: Pojo): Pojo;
// $parseJson(json: Pojo, opt?: ModelOptions): Pojo;
// $formatJson(json: Pojo): Pojo;
// $setJson
// $setDatabaseJson
// $setRelated
// this: T,
// relation: String | Relation,
// related: RelatedM | RelatedM[] | null | undefined
// ): T;
// $appendRelated
// this: T,
// relation: String | Relation,
// related: RelatedM | RelatedM[] | null | undefined
// ): T;
// $omit
// $pick
// $clone
// * If you add fields to your model, you get $relatedQuery typings for
// * free.
// *
// * Note that if you make any chained calls to the QueryBuilder,
// * though, you should apply a cast, which will make your code use not this
// * signatue, but the following signature.
// */
// $relatedQuery
// relationName: K,
// trxOrKnex?: Transaction | knex
// ): QueryBuilder
// * Builds a query that only affects the models related to this instance
// * through a relation. Note that this signature requires a
// * type cast (like bob.$relatedQuery<Animal>('pets')).
// */
// $relatedQuery
// trxOrKnex?: Transaction | knex
// ): QueryBuilder
// this: QM,
// expression: keyof this | RelationExpression,
// filters?: Filters
// trxOrKnex?: Transaction | knex
// ): QueryBuilder
// $traverse(filterConstructor: this, traverser: TraverserFunction): void;
// $transaction(): knex;
// $afterInsert(queryContext: QueryContext): Promise
// $afterUpdate(opt: ModelOptions, queryContext: QueryContext): Promise
// $beforeUpdate(opt: ModelOptions, queryContext: QueryContext): Promise
// $afterGet(queryContext: QueryContext): Promise
// $beforeDelete(queryContext: QueryContext): Promise
// $afterDelete(queryContext: QueryContext): Promise
}
| ({ "#id"?: string; "#ref"?: never; "#dbRef"?: never } & T)
| ({ "#id"?: never; "#ref": string; "#dbRef"?: never } & { [P in keyof T]?: never })
| ({ "#id"?: never; "#ref"?: never; "#dbRef": number } & { [P in keyof T]?: never });
| GraphModel<{ [P in NonFunctionPropertyNames
? DeepPartialGraphArray
? DeepPartialGraphModel
: T;
relate?: boolean | string[];
}
// transaction: Transaction;
}
columns: Array
}
table: string;
}
// knex?: knex;
force?: boolean;
table?: string;
}
p?: P; // comment and it works
d!: D;
}
// remove extends and things work
rig!: R; // comment this line and things work
}
// remove extends Model and things work
rs!: R[]; // comment out this line and things work
}
const d = new D();
await R.query().insertGraph({
d: d // change this to just be d and problem goes away!
});
}
console.log("here");
});
Cool, started re-looking at this and it looks like both the two repros in this issue by @koskimas are now fixed on master - It looks like the PR which fixed it is probably https://github.com/microsoft/TypeScript/pull/37589
@orta I used the included test project and confirmed it no longer errors in Version 3.9.0-dev.20200414
Most helpful comment
Oh, the original reproduction was also done using objection typings :smile: