I want to declare a simple type to replace any
in a piece of code. I know it will be some object-ish argument, so I could use Record<string, unknown>
, but I'd rather be a little more specific.
This would be ideal:
type MyObject = Record<string, string | string[] | number | boolean | MyObject>
but it gives the error
Type alias 'MyObject' circularly references itself.ts(2456)
I can get around this by cheating with interfaces:
type MyObject<T> = Record<string, string | string[] | number | boolean | T>
// eslint-disable-next-line @typescript-eslint/no-empty-interface
interface IMyObject extends MyObject<IMyObject>{}
Is there a way to do what I want, or should I just stick to Record<string, unknown>
?
The compiler gives up before it can realize that the type you are specifying is recursive in a supported way, because it does not probe the definition of the Record
utility type before checking for circularity. This is a design limitation of TypeScript. See microsoft/TypeScript#41164 for an explanation.
The fix here is to replace Record<string, XYZ>
with what it eventually becomes, a type with a string index signature like { [k: string]: XYZ }
:
type MyObject =
{ [k: string]: string | string[] | number | boolean | MyObject } // okay
which works without error.