A
arktype•3w ago
Micha

scope() how to bypass circular reference error?

I've implemented with Scope() successfully circular references, but somehow, I hit a limitation as this one still throws a circular reference error:
const types = scope({
queryValue: "namedDocument", // As soon as I add here namedDocument the error appears
queryValueObject: {
"[string]": "queryValue",
},

"namedDocument<metadata extends queryValueObject = Record<string, never>>": {
"data?": "metadata",
}
}).export();
const types = scope({
queryValue: "namedDocument", // As soon as I add here namedDocument the error appears
queryValueObject: {
"[string]": "queryValue",
},

"namedDocument<metadata extends queryValueObject = Record<string, never>>": {
"data?": "metadata",
}
}).export();
Error:
Type of property 'namedDocument' circularly references itself in mapped type '{ [k in "namedDocument<metadata extends queryValueObject>" as extractGenericName<k>]: GenericAst<conform<parseNextNameChar<skipWhitespace<extractParams<extractGenericParameters<k>>>, "", [], bootstrapAliases<...>>, array<...>>, { ...; }[k], "$", "$">; }'.ts(2615)
Type of property 'namedDocument' circularly references itself in mapped type '{ [k in "namedDocument<metadata extends queryValueObject>" as extractGenericName<k>]: GenericAst<conform<parseNextNameChar<skipWhitespace<extractParams<extractGenericParameters<k>>>, "", [], bootstrapAliases<...>>, array<...>>, { ...; }[k], "$", "$">; }'.ts(2615)
9 Replies
ssalbdivad
ssalbdivad•3w ago
Hmm, seems like a limitation of TypeScript. That type is quite hard to wrap my head around though, maybe worth seeing if it's possible to find another approach
Micha
MichaOP•3w ago
This is the working equivalent in typescript:
type QueryValue = NamedDocument
type QueryValueObject = {
[key: string]: QueryValue
}

type NamedDocument<metadata extends QueryValueObject = Record<string, never>> = {
data?: metadata
}
type QueryValue = NamedDocument
type QueryValueObject = {
[key: string]: QueryValue
}

type NamedDocument<metadata extends QueryValueObject = Record<string, never>> = {
data?: metadata
}
ssalbdivad
ssalbdivad•3w ago
Yeah I'm not saying it's impossible in native TS, but even with all the optimizations, there are still limitations on what TS will be able to resolve when having to parse and compare everything My guess is that it gets stuck trying to resolve the type of queryValueObject as a constraint since it has to be parsed in the key of the object
Micha
MichaOP•3w ago
Do you think this is solvable, and should I create a GitHub issue, or is it a general limitation?
ssalbdivad
ssalbdivad•3w ago
It's unlikely it is solvable with that syntax, although maybe with an alternate syntax it could work There are other limitations of TS though when it comes to inferring certain cyclic scopes. Frankly it's amazing as much works as it does, but it's unlikely there's much more I can do at least with the primary syntax in that regard
Micha
MichaOP•3w ago
Sound like you should consider writing your own compiler to get beyond such problems 😛
ssalbdivad
ssalbdivad•3w ago
Yeah I'll get right on that 😅 In the meantime you can remove the constraint as a workaround:
const types = type
.scope({
foo: { ss: "true" },
queryValue: "namedDocument<foo>", // As soon as I add here namedDocument the error appears
queryValueObject: {
"[string]": "queryValue"
},

"namedDocument<metadata>": {
"data?": "metadata"
}
})
.export()
const types = type
.scope({
foo: { ss: "true" },
queryValue: "namedDocument<foo>", // As soon as I add here namedDocument the error appears
queryValueObject: {
"[string]": "queryValue"
},

"namedDocument<metadata>": {
"data?": "metadata"
}
})
.export()
I guess that is the only place in the type it even uses the scope though haha
Micha
MichaOP•3w ago
I think I go for now with this one:
const types = type
.scope({
queryValue: "namedDocument<Record<string, unknown>>",
queryValueObject: {
"[string]": "queryValue",
},

"namedDocument<metadata extends Record<string, unknown>>": {
"data?": "metadata",
},
})
.export();
const types = type
.scope({
queryValue: "namedDocument<Record<string, unknown>>",
queryValueObject: {
"[string]": "queryValue",
},

"namedDocument<metadata extends Record<string, unknown>>": {
"data?": "metadata",
},
})
.export();
ssalbdivad
ssalbdivad•3w ago
Glad you found that something to tide you over while I finish that new compiler 😛

Did you find this page helpful?