# Anytype best practices

**URL:** <https://ziggit.dev/t/anytype-best-practices/18144>\
**Category:** Explain\
**Tags:** language\
**Created:** [October 29, 2026, 6:02pm UTC](https://ziggit.dev/t/anytype-best-practices/18144 "2026-10-29T18:02:15Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![grurbo](https://ziggit.dev/user_avatar/ziggit.dev/grurbo/32/10367_2.png) [@grurbo](https://ziggit.dev/u/grurbo)\
**Post date:** [October 29, 2026, 6:02pm UTC](https://ziggit.dev/t/anytype-best-practices/18144/1 "2026-10-29T18:02:15Z")

</div>

So for background I’ve been using zig since ~0.12 but I’ve only recently really dug into the comptime/metaprogramming features. Whenever I’ve had to use anytype (or like an `inline for` that calls the same fn/access the same field, that sort of thing), I get a bad taste in my mouth. It feels like every implicit contract I add is going to make retracing my steps later that much harder. Maybe that’s just the trade-off, but my question is:

Does anyone have examples of strategies/design patterns I’m missing out on that can help narrow anytype/make it more explicit? For now I’m just trying to add good comments and putting in a few `@compileError`s.

---

<div class="post-metadata">

**Author:** ![Sze](https://ziggit.dev/user_avatar/ziggit.dev/sze/32/496_2.png) [@Sze](https://ziggit.dev/u/Sze)\
**Post date:** [October 29, 2026, 7:48pm UTC](https://ziggit.dev/t/anytype-best-practices/18144/2 "2026-10-29T19:48:28Z")

</div>

My main advice would be to only use it, if it is actually required, so if an explicitly declared struct or tagged union type would work to model the parameter then use that, instead of using `anytype` out of laziness.

Then when you do use it, make sure you have doc tests of the function (`test functionName {...}`) that demonstrate all the possible usecases, that way you have both testing and usage examples showing up in the documentation / making sure the intended api is documented and that it remains supported with future changes.

---

<div class="post-metadata">

**Author:** ![grurbo](https://ziggit.dev/user_avatar/ziggit.dev/grurbo/32/10367_2.png) [@grurbo](https://ziggit.dev/u/grurbo)\
**Post date:** [October 29, 2026, 7:54pm UTC](https://ziggit.dev/t/anytype-best-practices/18144/3 "2026-10-29T19:54:47Z")

</div>

Yea my current project is using a good amount of anytype + interfaces and I’m leaning into interfaces as much as possible. Anytype has kinda been the escape hatch for things I can’t represent otherwise

---

<div class="post-metadata">

**Author:** ![alanza](https://ziggit.dev/user_avatar/ziggit.dev/alanza/32/6006_2.png) [@alanza](https://ziggit.dev/u/alanza)\
**Post date:** [October 29, 2026, 11:10pm UTC](https://ziggit.dev/t/anytype-best-practices/18144/4 "2026-10-29T23:10:17Z")

</div>

Why interfaces?

---

<div class="post-metadata">

**Author:** ![zeeqeeng](https://ziggit.dev/letter_avatar_proxy/v4/letter/z/8baadc/32.png) [@zeeqeeng](https://ziggit.dev/u/zeeqeeng)\
**Post date:** [October 29, 2026, 11:52pm UTC](https://ziggit.dev/t/anytype-best-practices/18144/5 "2026-10-29T23:52:31Z")

</div>

I found that `anytype` is suitable for expecting a tuple where the length of properties is runtime-known or variable (`std.debug.print`) while `type` is good for generics parameters, e.g., `std.mem.find`, to build a reusable library.

---

<div class="post-metadata">

**Author:** ![mmirj](https://ziggit.dev/user_avatar/ziggit.dev/mmirj/32/10463_2.png) [@mmirj](https://ziggit.dev/u/mmirj)\
**Post date:** [October 30, 2026, 12:08am UTC](https://ziggit.dev/t/anytype-best-practices/18144/6 "2026-10-30T00:08:37Z")

</div>

Use normal types when you can. Once one thing is generic, every struct that holds it and every function that uses it has to be generic too.

And like @zeeqeeng said, if the type depends on something known at compile time, pass it in, the way `std.mem.find` takes `comptime T: type`.

For the anytype that’s left, the `@compileError`s you’re adding are the right idea.

---

<div class="post-metadata">

**Author:** ![grurbo](https://ziggit.dev/user_avatar/ziggit.dev/grurbo/32/10367_2.png) [@grurbo](https://ziggit.dev/u/grurbo)\
**Post date:** [October 30, 2026, 4:43am UTC](https://ziggit.dev/t/anytype-best-practices/18144/7 "2026-10-30T04:43:22Z")

</div>

so for example, in one part of this project:

At startup an array of different function pointers is assembled based on runtime parameters. The function to turn all these many structs into this interface (literally just looping through every decl and calling `toInterface()`) is accomplished through an inline for loop/anytype situation, but everything from then on uses the interface. It’s surely possible to do the same thing without an interface (it’s already halfway there) but this seemed like the right place to draw the boundary

---

<div class="post-metadata">

**Author:** ![gonzo](https://ziggit.dev/user_avatar/ziggit.dev/gonzo/32/54_2.png) [@gonzo](https://ziggit.dev/u/gonzo)\
**Post date:** [October 30, 2026, 9:53am UTC](https://ziggit.dev/t/anytype-best-practices/18144/8 "2026-10-30T09:53:37Z")

</div>

> [@alanza](#):
>
> Why interfaces?

But why male models?

Sorry, I just couldn’t resist. Apologies to moderators.

---

<div class="post-metadata">

**Author:** ![alanza](https://ziggit.dev/user_avatar/ziggit.dev/alanza/32/6006_2.png) [@alanza](https://ziggit.dev/u/alanza)\
**Post date:** [October 30, 2026, 11:05am UTC](https://ziggit.dev/t/anytype-best-practices/18144/9 "2026-10-30T11:05:49Z")

</div>

nono, my question was less intelligent than the one you answered. I meant why does your project have interfaces?

---

<div class="post-metadata">

**Author:** ![grurbo](https://ziggit.dev/user_avatar/ziggit.dev/grurbo/32/10367_2.png) [@grurbo](https://ziggit.dev/u/grurbo)\
**Post date:** [October 31, 2026, 3:27am UTC](https://ziggit.dev/t/anytype-best-practices/18144/10 "2026-10-31T03:27:24Z")

</div>

I’m repeatedly looping through an arbitrarily sized array of pointers to structs that operate on the same data. There could even be duplicates that just have different options set up, so an interface seemed appropriate. The program is _extremely_ i/o bottlenecked so I figure the most important thing is finding an effective way of sharing the data (i.e. every struct operates on each delimited chunk before moving on)
