# New Idea for file level structs

**URL:** <https://ziggit.dev/t/new-idea-for-file-level-structs/13805>\
**Category:** Brainstorming\
**Tags:** language\
**Created:** [January 4, 2026, 10:42pm UTC](https://ziggit.dev/t/new-idea-for-file-level-structs/13805 "2026-01-04T22:42:06Z")\
**Posts on this page:** 12\
**Page:** 1

<div class="post-metadata">

**Author:** ![burakssen](https://ziggit.dev/letter_avatar_proxy/v4/letter/b/dc4da7/32.png) [@burakssen](https://ziggit.dev/u/burakssen)\
**Post date:** [January 4, 2026, 10:42pm UTC](https://ziggit.dev/t/new-idea-for-file-level-structs/13805/1 "2026-01-04T22:42:06Z")

</div>

I’m not sure if this has been discussed somewhere already, but I wanted to get feedback on this idea, whether it’s feasible and whether it aligns with the direction of the Zig language.

As we know Zig has file level structs that we can define as follows:

```zig
const Foo = @This();

value: i32,

pub fn init(val: i32) Foo {
    return .{
        .value = val,
    };
}

```

and we can use it like this:

```zig
const Foo = @import("foo.zig");

const foo = Foo.init(10);

```

I wanted to ask if this could be possible for `union(enum)`

```zig
const UnionEnum = union(enum) {
    A: struct {a: i32, b:i32},
    B: struct {c: bool},
}

```

can be:

```zig

// We can define something like this:

const UnionEnum = @union(enum);

A: struct {a: i32, b:i32},
B: struct {c: bool},

```

and it would work as same principle.

This is just an idea that I came up please don’t take it too seriously just wanted to learn if its feasible or not.

Thank you in advance.

---

<div class="post-metadata">

**Author:** ![GigaGrunch](https://ziggit.dev/user_avatar/ziggit.dev/gigagrunch/32/1823_2.png) [@GigaGrunch](https://ziggit.dev/u/GigaGrunch)\
**Post date:** [January 4, 2026, 10:48pm UTC](https://ziggit.dev/t/new-idea-for-file-level-structs/13805/2 "2026-01-04T22:48:09Z")

</div>

I see one problem with this: Every file is always a struct. You dont need to do anything for that and you can’t do anything against that. If your example file is completely empty, you can still import and use it as a struct. It would be empty as well, of course. My point is that there is no place that says “this file is a struct" that you could change to say “this file is a union" or whatever.

---

<div class="post-metadata">

**Author:** ![burakssen](https://ziggit.dev/letter_avatar_proxy/v4/letter/b/dc4da7/32.png) [@burakssen](https://ziggit.dev/u/burakssen)\
**Post date:** [January 4, 2026, 10:51pm UTC](https://ziggit.dev/t/new-idea-for-file-level-structs/13805/3 "2026-01-04T22:51:37Z")

</div>

Yeah I guess so, if someone really wanted to implement this I guess the representation of file structs needs to change and I don’t think that’s feasible. I just get annoyed sometimes because of this: `const UnionEnum = @import("union_enum.zig").UnionEnum;` because I need to include with another access. It makes me feel like I am doing something wrong but I know there is nothing wrong.

---

<div class="post-metadata">

**Author:** ![GigaGrunch](https://ziggit.dev/user_avatar/ziggit.dev/gigagrunch/32/1823_2.png) [@GigaGrunch](https://ziggit.dev/u/GigaGrunch)\
**Post date:** [January 4, 2026, 11:00pm UTC](https://ziggit.dev/t/new-idea-for-file-level-structs/13805/4 "2026-01-04T23:00:11Z")

</div>

It would be nice. As long as it’s just about making that a bit nicer though, I doubt it will ever happen. If there would be some real advantages to it, it would be more likely.

By the way, I found a thread about basically the same topic. It also hasn’t a lot of discussion though: [.zig files as enum containers](https://ziggit.dev/t/zig-files-as-enum-containers/13290)

---

<div class="post-metadata">

**Author:** ![lrworth](https://ziggit.dev/user_avatar/ziggit.dev/lrworth/32/7491_2.png) [@lrworth](https://ziggit.dev/u/lrworth)\
**Post date:** [January 5, 2026, 7:41am UTC](https://ziggit.dev/t/new-idea-for-file-level-structs/13805/5 "2026-01-05T07:41:39Z")

</div>

It would also be awesome if a file could be a function or a const value (the latter would make zig a configuration file format). You could do something in the file extension, e.g. pi.const.zig could just contain some approximation of pi, generated by a block.

---

<div class="post-metadata">

**Author:** ![tsdtas](https://ziggit.dev/user_avatar/ziggit.dev/tsdtas/32/3512_2.png) [@tsdtas](https://ziggit.dev/u/tsdtas)\
**Post date:** [January 5, 2026, 7:52am UTC](https://ziggit.dev/t/new-idea-for-file-level-structs/13805/6 "2026-01-05T07:52:05Z")

</div>

How is that more ergonomic than something like `@import(constants.zig).pi`?

---

<div class="post-metadata">

**Author:** ![lrworth](https://ziggit.dev/user_avatar/ziggit.dev/lrworth/32/7491_2.png) [@lrworth](https://ziggit.dev/u/lrworth)\
**Post date:** [January 5, 2026, 8:06am UTC](https://ziggit.dev/t/new-idea-for-file-level-structs/13805/7 "2026-01-05T08:06:04Z")

</div>

Because it would give a standard config file format. There are at least [ziggy](https://ziggy-lang.io) and Zon trying to do this, but they are restricted by not actually being zig.

---

<div class="post-metadata">

**Author:** ![mnemnion](https://ziggit.dev/user_avatar/ziggit.dev/mnemnion/32/2478_2.png) [@mnemnion](https://ziggit.dev/u/mnemnion)\
**Post date:** [January 5, 2026, 4:21pm UTC](https://ziggit.dev/t/new-idea-for-file-level-structs/13805/8 "2026-01-05T16:21:02Z")

</div>

I thought about this a bit myself.

In [Zitron](https://github.com/mnemnion/zitron), the parser-compiler can emit the token enums as their own file. In Zig there’s no special reason to prefer this, because circular imports are allowed, so a separate tokenizer file can import the enums from the parser, and the parser can import the tokenizer, and everything just works. But it’s also nice not to do that.

`zitron` names that file after the `%token_enum_type`, defaulting to `TokenKind`, so, `TokenKind.zig`. But this is irregular, because it’s a namespace file, not an instantiable-struct file. I didn’t think this small deviation from doctrine was worth correcting.

Then importing that looks like this:

```zig
const TokenKind = @import("TokenKind.zig").TokenKind;

```

Which is, not bad, not great, a few sacrifices are acceptable when generating code. In my opinion at least.

Still, “wouldn’t it be nice” if the file could just be the enum? Syntactically, no problem:

```zig
//! This file is an enum
enum(u8); // Illegal expression currently

fee,
fie,
foe, 
fum,
// Whatever else

```

But this goes from “files are just structs” to “files are structs by default, but they can actually be any container type, be sure to check for a special little bit of irregular syntax at the top”.

Which I’m not completely opposed to, part of me continues to think that would be neat.

But it brings no new abilities to the language, it doesn’t lead to safer or more efficient code, it’s just sugar. I would say it makes import statements cleaner, but makes program structure slightly harder to understand, and expands the answer to “what is a file” from a short sentence to a fairly long one.

I’d call that a wash, but even if we say it’s net beneficial, that benefit is fairly small. All things considered it doesn’t seem worth it.

---

<div class="post-metadata">

**Author:** ![jumpnbrownweasel](https://ziggit.dev/user_avatar/ziggit.dev/jumpnbrownweasel/32/263_2.png) [@jumpnbrownweasel](https://ziggit.dev/u/jumpnbrownweasel)\
**Post date:** [January 5, 2026, 5:42pm UTC](https://ziggit.dev/t/new-idea-for-file-level-structs/13805/9 "2026-01-05T17:42:42Z")

</div>

I don’t even use `CapitalizedStruct.zig` files because they’re not fully capable structs without generics. (I realize an `fn` is needed for generic structs.) I think of files as purely namespaces, even though they are structs of course. This is simpler and more consistent to me.

---

<div class="post-metadata">

**Author:** ![mnemnion](https://ziggit.dev/user_avatar/ziggit.dev/mnemnion/32/2478_2.png) [@mnemnion](https://ziggit.dev/u/mnemnion)\
**Post date:** [January 5, 2026, 5:55pm UTC](https://ziggit.dev/t/new-idea-for-file-level-structs/13805/10 "2026-01-05T17:55:31Z")

</div>

I tend not to myself, for a similar reason: it’s not uncommon that I decide to turn a struct into a type-returning function, and if the struct is a file, that stylistically invalidates the name of the file.

I don’t treat this as a rule but it’s definitely my habit.

---

<div class="post-metadata">

**Author:** ![ericlang](https://ziggit.dev/user_avatar/ziggit.dev/ericlang/32/8515_2.png) [@ericlang](https://ziggit.dev/u/ericlang)\
**Post date:** [January 5, 2026, 6:57pm UTC](https://ziggit.dev/t/new-idea-for-file-level-structs/13805/11 "2026-01-05T18:57:54Z")

</div>

> [@jumpnbrownweasel](#):
>
> I think of files as purely namespaces, even though they are structs of course. This is simpler and more consistent to me.

For me too. Apart from the fact it looks ugly in my file-list.  
I rather have a type `position.Position` from a file position.zig.

---

<div class="post-metadata">

**Author:** ![grayhatter](https://ziggit.dev/letter_avatar_proxy/v4/letter/g/73ab20/32.png) [@grayhatter](https://ziggit.dev/u/grayhatter)\
**Post date:** [January 5, 2026, 11:39pm UTC](https://ziggit.dev/t/new-idea-for-file-level-structs/13805/12 "2026-01-05T23:39:19Z")

</div>

I’ve wanted a file level union(enum) myself for nearly as long as I’ve been writing zig. About a year later, I care a lot less. Would it be nice? Probably, would it be worth the cost to zig’s complexity budget? Absolutely not. `const Thing = @import("thing.zig").Thing` is not a perfect and as clean as I want, but truth be told, as soon as I type `git commit` I don’t care anymore. I’m ok with it. File level structs are a very nice bit of language sugar, but the namespace for the whole language doesn’t need to be perfectly flat. Especially when you also have to answer the question: are you sure that union doesn’t belong somewhere else?
