# Fieldnames for an instance of a structure

**URL:** <https://discourse.julialang.org/t/fieldnames-for-an-instance-of-a-structure/137701>\
**Category:** New to Julia\
**Created:** [June 19, 2026, 2:16pm UTC](https://discourse.julialang.org/t/fieldnames-for-an-instance-of-a-structure/137701 "2026-06-19T14:16:42Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![Boris](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/boris/32/3306_2.png) [@Boris](https://discourse.julialang.org/u/Boris)\
**Post date:** [June 19, 2026, 2:16pm UTC](https://discourse.julialang.org/t/fieldnames-for-an-instance-of-a-structure/137701/1 "2026-06-19T14:16:42Z")

</div>

Hi, been a while since I have asked a dumb question in `New to Julia` so here we go.

Is there a way to define the function `fieldnames`or similar to give me the field names for an instance of a structure? I would like to see the fields of mine (or other people’s) custom structures.

AFAIK, `fieldnames` works on the type, and it throws an error if you use it on an instance of the structure. But for that you need to know the custom type name, that you might have forgotten (not that that would ever happen to me).

However, a hack, that I have been using is misspelling a field on purpose, then the error shows all the available field names. Is there a better way? I have seen some topics on the question, such as [this one](https://discourse.julialang.org/t/display-struct-definition/6564), but that solution seems even worse than my hack.

Here is what I mean  
**Code snippet**

```julia-auto
struct Foo{T}
    a::T
    b::T
end # define a struct and forget its fields 3 secs later because I have a memory span of a goldfish
Fooinst = Foo(4,2) # create an instance
fieldnames(Foo) # this works, prints the fields
fieldnames(Fooinst) # this does not work because it is not on the type, but I need to know the type name "Foo"
Fooinst.c # misspell on purpose, this works, because the error throws the field names

```

**Output:**

```julia-auto
julia> struct Foo{T}
           a::T
           b::T
       end # define a struct and forget its fields 3 secs later because I have a memory span of a goldfish

julia> Fooinst = Foo(4,2) # create an instance
Foo{Int64}(4, 2)

julia> fieldnames(Foo) # this works, prints the fields
(:a, :b)

julia> fieldnames(Fooinst) # this does not work because it is not on the type, but I need to know the type name "Foo"
ERROR: MethodError: no method matching fieldnames(::Foo{Int64})
The function `fieldnames` exists, but no method is defined for this combination of argument types.

Closest candidates are:
  fieldnames(::Core.TypeofBottom)
   @ Base runtime_internals.jl:339
  fieldnames(::Type{<:Tuple})
   @ Base runtime_internals.jl:341
  fieldnames(::UnionAll)
   @ Base runtime_internals.jl:338
  ...

Stacktrace:
 [1] top-level scope
   @ c:\Users\bblagov\Dropbox\JuliaNew\BEAVARs\dev\devCPZ.jl:27

julia> Fooinst.c # misspell on purpose, this works, because the error throws the field names
ERROR: FieldError: type Foo has no field `c`, available fields: `a`, `b`
Stacktrace:
 [1] getproperty(x::Foo{Int64}, f::Symbol)
   @ Base .\Base_compiler.jl:54
 [2] top-level scope
   @ c:\Users\bblagov\Dropbox\JuliaNew\BEAVARs\dev\devCPZ.jl:28

```

The last line gives me the info that I need:

ERROR: FieldError: type Foo has no field `c`, **available fields: `a`, `b`**

---

<div class="post-metadata">

**Author:** ![matthias314](https://avatars.discourse-cdn.com/v4/letter/m/a88e4f/32.png) [@matthias314](https://discourse.julialang.org/u/matthias314)\
**Post date:** [June 19, 2026, 2:34pm UTC](https://discourse.julialang.org/t/fieldnames-for-an-instance-of-a-structure/137701/2 "2026-06-19T14:34:25Z")

</div>

What about `fieldnames(typeof(Fooinst))`?

---

<div class="post-metadata">

**Author:** ![BeastyBlacksmith](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/beastyblacksmith/32/4741_2.png) [@BeastyBlacksmith](https://discourse.julialang.org/u/BeastyBlacksmith)\
**Post date:** [June 21, 2026, 6:21pm UTC](https://discourse.julialang.org/t/fieldnames-for-an-instance-of-a-structure/137701/3 "2026-06-21T18:21:21Z")

</div>

There is also `propertynames` which might give different answers, but depending on your usecase that might not matter. Also usually it does give the same answer.

---

<div class="post-metadata">

**Author:** ![mcabbott](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mcabbott/32/6603_2.png) [@mcabbott](https://discourse.julialang.org/u/mcabbott)\
**Post date:** [June 21, 2026, 9:38pm UTC](https://discourse.julialang.org/t/fieldnames-for-an-instance-of-a-structure/137701/4 "2026-06-21T21:38:55Z")

</div>

Seems like this is the issue:

> <https://github.com/JuliaLang/julia/issues/34788#issuecomment-587138355>
>
> Currently, \`fieldnames\` returns the fields ascribed to a \_type\_, whereas \`proper…tynames\` returns the properties of an \_instance\_:
> \`\`\`
> \_
> \_ \_ \_(\_)\_ | Documentation: https://docs.julialang.org
> (\_) | (\_) (\_) |
> \_ \_ \_| |\_ \_\_ \_ | Type "?" for help, "\]?" for Pkg help.
> | | | | | | |/ \_\` | |
> | | |\_| | | | (\_| | | Version 1.2.0 (2019-08-20)
> \_/ |\\\_\_'\_|\_|\_|\\\_\_'\_| | Official https://julialang.org/ release
> |\_\_/ |
> 
> julia\> struct A
> x
> end
> 
> julia\> a = A(1.0)
> A(1.0)
> 
> julia\> fieldnames(a)
> ERROR: MethodError: no method matching fieldnames(::A)
> 
> julia\> propertynames(a)
> (:x,)
> 
> julia\> fieldnames(A)
> (:x,)
> 
> julia\> propertynames(A)
> (:name, :super, :parameters, :types, :names, :instance, :layout, :size, :ninitialized, :uid, :abstract, :mutable, :hasfreetypevars, :isconcretetype, :isdispatchtuple, :isbitstype, :zeroinit, :isinlinealloc, Symbol("llvm::StructType"), Symbol("llvm::DIType"))
> \`\`\`
> Since properties are abstractions of fields, I feel that fields and properties should be treated more consistently. I have two independent suggestions:
> 
> 1. Currently, the fallback for \`propertynames\` is \`propertynames(x) = fieldnames(typeof(x))\`. My suggestion would be to define the corresponding fallback \`fieldnames(x) = fieldnames(typeof(x))\` as well. This seems to me to be the only sensible meaning when \`x\` is not a type. Furthermore, this addition would be non-breaking.
> 
> 2. IMHO, the result of \`propertynames(A)\` in the example above is unexpected. I suggest defining the fallback \`propertyname(x::DataType) = fieldnames(x)\` (and related methods for special types such as \`UnionAll\` and \`Tuple\`). I believe this would technically be a breaking change, but it would make the behavior of \`propertynames(A)\` consistent with \`fieldnames(A)\` and (arguably) more expected.

Julia 0.7, which is 1.0 with deprecation warnings, behaves as follows:

```julia-auto
julia> fieldnames(Foo) # this works, prints the fields
(:a, :b)

julia> fieldnames(Fooinst) # this does not work because it is not on the type, but I need to know the type name "Foo"
┌ Warning: `fieldnames(v)` is deprecated, use `fieldnames(typeof(v))` instead.
│ caller = top-level scope at none:0
└ @ Core none:0
(:a, :b)

julia> VERSION
v"0.7.0"

```

---

<div class="post-metadata">

**Author:** ![joa-quim](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/joa-quim/32/227_2.png) [@joa-quim](https://discourse.julialang.org/u/joa-quim)\
**Post date:** [June 21, 2026, 11:08pm UTC](https://discourse.julialang.org/t/fieldnames-for-an-instance-of-a-structure/137701/5 "2026-06-21T23:08:27Z")

</div>

I use these two in GMT.jl

```julia-auto
fields(arg) = fieldnames(typeof(arg))
fields(arg::Array) = fieldnames(typeof(arg[1]))

```

---

<div class="post-metadata">

**Author:** ![Benny](https://avatars.discourse-cdn.com/v4/letter/b/49beb7/32.png) [@Benny](https://discourse.julialang.org/u/Benny)\
**Post date:** [June 21, 2026, 11:45pm UTC](https://discourse.julialang.org/t/fieldnames-for-an-instance-of-a-structure/137701/6 "2026-06-21T23:45:06Z")

</div>

I don’t even know why that issue is still open. Fields are defined along with types, while properties can be defined in associated methods and vary with instances. The different inputs make sense for `fieldnames` and `propertynames`, and the latter reasonably falls back to the former: `propertynames(x) = fieldnames(typeof(x))`.

I’ll also point out that these deliberately avoided supporting both instances and types as inputs because types themselves are instances of types. The fallback `__names(instance) =__names(typeof(instance))` would recurse endlessly, so it would have to stop somewhere like `__names(t::Type) = do_something(t)`. In that case, we would be forced to handle types of types in manual branches: `[x isa Type ?__names(typeof(x)) : __names(x) for x in [1im, Complex]]`. That sort of `typeof`-forwarding only works when types of types don’t have the characteristic of interest, like `eltype`.

---

<div class="post-metadata">

**Author:** ![Boris](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/boris/32/3306_2.png) [@Boris](https://discourse.julialang.org/u/Boris)\
**Post date:** [June 22, 2026, 11:42am UTC](https://discourse.julialang.org/t/fieldnames-for-an-instance-of-a-structure/137701/7 "2026-06-22T11:42:30Z")

</div>

@matthias314 This works, I haven’t thought about it, thanks! My only argument against it is that it is just a bit long (requires two tab completions).

But using `propertynames` does exactly what I expected, just didn’t know this existed. Thanks @BeastyBlacksmith!
