My code was working just fine until I tried to wrap a function definition with a decorator (by "decorator" I just mean a higher-order function that takes one function as a param and return another function, I'm not talking about the upcoming decorator syntax). When I use this decorator, I get the error Type alias 'Thing' circularly references itself. Why is this happening?
Below is the broken code sample (This is an extremely simplified version that tries to simply showcase the problem I'm running into).
const decorate = (fn: () => boolean) => fn
const thing = {
fn: decorate(() => {
type Thing = typeof thing
const thing_: Thing = thing
return 'fn' in thing_
})
}
Compare that to the following code snippet, which works just fine. I'm just removing the call to decorate (which is just an identity function in this simplified example).
const decorate = (fn: () => boolean) => fn
const thing = {
fn: () => {
type Thing = typeof thing
const thing_: Thing = thing
return 'fn' in thing_
}
}
I can even take my broken example and replace the decorate function with the following generic function, and it'll magically start working, even though the two definitions should be functionally equivalent in the specific way they're being used.
const decorate = <T>(fn: T): T => fn
Update: For anyone who's interested, here's how I ended up fixing my issue
I had to explicitly tell TypeScript what the type of my function was, so I put it in an IFEE and assigned it to a variable with a declared type, like this:
const decorate = (fn: () => boolean) => fn
const thing = {
fn: (() => {
type MyFnType = () => boolean
const fn: MyFnType = decorate(() => {
type Thing = typeof thing
const thing_: Thing = thing
return 'fn' in thing_
})
return fn
})()
}
It's not pretty, but it works around this issue.
(Note that this isn't an answer to my own question, as my question is asking why I have to do a workaround like this, I'm not necessarily asking how to do it).