Improve type inference for circular references in object initializers
See original GitHub issueWhen you have something like this (also see a playground):
function makeFoo<T>(fn: () => T): () => T {
// do some work here ...
return function() {
// ... or here
return fn()
}
}
const obj = {
name: 'test',
foo: makeFoo(() => obj.name.length)
}
type of obj
will be infered as any
, because in order to determine type of obj
typescript first looks at return type of makeFoo(...)
which uses obj
.
The actual error is this: 'obj' implicitly has type 'any' because it does not have a type annotation and is referenced directly or indirectly in its own initializer.(7022)
What if we could give some hint to a compiler to handle this case? Maybe like this:
const obj = {
name: 'test',
foo: makeFoo(() => obj.name.length) as prop // or a better name
}
Right now I have a workaround for this:
function getter<T, R>(t: T, k: keyof T, value: R) {
Object.defineProperty(t, k, {value, enumerable: true})
return value
}
const obj = {
name: 'test',
get foo() {
return getter(obj, 'foo', makeFoo(() => obj.name.length))
}
}
but it would be cool if it could be done more easily.
Issue Analytics
- State:
- Created 2 years ago
- Reactions:4
- Comments:12 (6 by maintainers)
Top Results From Across the Web
Swift Lazy Property Initialization Circular Reference ...
The circular reference is in the type inferencing: It's the fact that foo 's type depends on self.foo 's type, which depends on...
Read more >Dealing with circular type references in Mobx-state-tree
The idea is to augment the inferred type of Snippet$1 model with a manual specification of types of attributes which cause circular reference....
Read more >Remove or allow a circular reference - Microsoft Support
If you're using Excel 2010 or later, click File > Options > Formulas. · In the Calculation options section, select the Enable iterative...
Read more >Custom pluggable types for ... - The Checker Framework Manual
31.1 Invariant array types; 31.2 Context-sensitive type inference for ... indicating that ref must be a reference to a non-null object.
Read more >numba.ast_type_inference — numba 0.5.0 documentation
Initialize with a minivect context, a Python ast, and a function type with a given or ... Raise an exception for a circular...
Read more >Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start FreeTop Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Top GitHub Comments
Yeah, this makes sense. TypeScript uses a recursive descent parsing algorithm, and the sort of algorithm I was describing would require an entirely different type of parsing algorithm. Not only would it take a whole lot of work to switch, it’ll also add a lot of complexity to the codebase, and this particular issue isn’t an extremely common one.
I don’t think I’ll try to actually make a PR - I can tell that this sort of thing would be a giant refactor, and it’s certainly not a task I would be capable of, especially considering that I currently know nothing about the TypeScript codebase.
Ok, thanks for helping me understand 😃
The mechanism you’re describing here where, upon detecting a possible circularity, we just sort of put the relevant question on pause and come back to it later - this isn’t really compatible with the straightforward caching recursive descent that the checker is written in.
It’s instructive to look at the call stack at the point that we log the circularity error and see how every caller in that path (of which the incoming call stack is could be practically any function in the checker) would have to be basically completely rewritten to handle the answer of “ask me again later”.
We also need to be able to detect circularities instead of looping forever. For example, if you wrote
then any sort of work-deferring mechanism needs to be able to detect when it’s looping forever so that it doesn’t attempt to infer an infinite sequence of
[0, [0, [0, [0, [0, [0, ...
.The relevant codepaths in the checker here are not especially complicated (relatively speaking) and I’d encourage you to try a PR to understand the problem more deeply. Not to be glib, but if this were low-hanging fruit, we would have done it already 😉. Again, it’s not impossible, but it’s not at all a straightforward fix - we’d have to rewrite very large portions of the entire checker.