# Extract type name only from parametric type

**URL:** <https://discourse.julialang.org/t/extract-type-name-only-from-parametric-type/14188>\
**Category:** General Usage\
**Tags:** question, parametric-types\
**Created:** [August 28, 2018, 12:55pm UTC](https://discourse.julialang.org/t/extract-type-name-only-from-parametric-type/14188 "2018-08-28T12:55:22Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![e3c6](https://avatars.discourse-cdn.com/v4/letter/e/e79b87/32.png) [@e3c6](https://discourse.julialang.org/u/e3c6)\
**Post date:** [August 28, 2018, 12:55pm UTC](https://discourse.julialang.org/t/extract-type-name-only-from-parametric-type/14188/1 "2018-08-28T12:55:22Z")

</div>

Suppose I have a function that takes a value of a parametric type, for example:

```julia
abstract type AbstractMyType{Q} end
struct MyType1{Q} <: AbstractMyType{Q} end
struct MyType2{Q} <: AbstractMyType{Q} end

f(x::T) where {T<:AbstractMyType} = # something...

```

Inside `f`, I want to determine the type of `x` in a generic way, but without the parameters. For example, if `f` si called with `x::MyType1{Int}`, I want to have a variable inside `f` that holds the value `MyType1`.

For example one way to do it is to define methods:

```julia
f(x::T) where {T<:MyType1} = begin t = MyType1; #=more code... =# end
f(x::T) where {T<:MyType2} = begin t = MyType2; #=more code... =# end

```

But this gets repetitive if I have many derived types. Is there a better way?

---

<div class="post-metadata">

**Author:** ![mohamed82008](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mohamed82008/32/18171_2.png) [@mohamed82008](https://discourse.julialang.org/u/mohamed82008)\
**Post date:** [August 28, 2018, 1:41pm UTC](https://discourse.julialang.org/t/extract-type-name-only-from-parametric-type/14188/2 "2018-08-28T13:41:01Z")

</div>

One way using metaprogramming:

```julia
for T in (MyType1, MyType2)
    @eval getname(::Type{<:$T}) = $T
end
f(x::T) = begin t = getname(T); #=more code... =# end

```

---

<div class="post-metadata">

**Author:** ![e3c6](https://avatars.discourse-cdn.com/v4/letter/e/e79b87/32.png) [@e3c6](https://discourse.julialang.org/u/e3c6)\
**Post date:** [August 28, 2018, 1:43pm UTC](https://discourse.julialang.org/t/extract-type-name-only-from-parametric-type/14188/3 "2018-08-28T13:43:33Z")

</div>

This assumes you know the list of derived types `(MyType1, MyType2)`. Hopefully there is a generic way?

---

<div class="post-metadata">

**Author:** ![mohamed82008](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mohamed82008/32/18171_2.png) [@mohamed82008](https://discourse.julialang.org/u/mohamed82008)\
**Post date:** [August 28, 2018, 1:46pm UTC](https://discourse.julialang.org/t/extract-type-name-only-from-parametric-type/14188/4 "2018-08-28T13:46:10Z")

</div>

See the discussion in [Stripping parameter from parametric types](https://discourse.julialang.org/t/stripping-parameter-from-parametric-types/8293)

---

<div class="post-metadata">

**Author:** ![mohamed82008](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mohamed82008/32/18171_2.png) [@mohamed82008](https://discourse.julialang.org/u/mohamed82008)\
**Post date:** [August 28, 2018, 1:47pm UTC](https://discourse.julialang.org/t/extract-type-name-only-from-parametric-type/14188/5 "2018-08-28T13:47:58Z")

</div>

This is probably bad practice but here is the relevant code from that post:

```julia
name(T::DataType) = T.name
name(T::UnionAll) = name(T.body)

```

---

<div class="post-metadata">

**Author:** ![e3c6](https://avatars.discourse-cdn.com/v4/letter/e/e79b87/32.png) [@e3c6](https://discourse.julialang.org/u/e3c6)\
**Post date:** [August 28, 2018, 1:50pm UTC](https://discourse.julialang.org/t/extract-type-name-only-from-parametric-type/14188/6 "2018-08-28T13:50:07Z")

</div>

`name` returns a `Core.TypeName`. This is not the same as the type.

---

<div class="post-metadata">

**Author:** ![mohamed82008](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mohamed82008/32/18171_2.png) [@mohamed82008](https://discourse.julialang.org/u/mohamed82008)\
**Post date:** [August 28, 2018, 1:55pm UTC](https://discourse.julialang.org/t/extract-type-name-only-from-parametric-type/14188/7 "2018-08-28T13:55:24Z")

</div>

Ya sorry missed that, `name(::Type{T}) where T = eval(nameof(T))` also works but it is not as performant as my first solution, so you can call it a tradeoff.

---

<div class="post-metadata">

**Author:** ![e3c6](https://avatars.discourse-cdn.com/v4/letter/e/e79b87/32.png) [@e3c6](https://discourse.julialang.org/u/e3c6)\
**Post date:** [August 28, 2018, 2:01pm UTC](https://discourse.julialang.org/t/extract-type-name-only-from-parametric-type/14188/8 "2018-08-28T14:01:14Z")

</div>

Thanks that works. But the computation of `T` here is not occurring at compile time? Is this what you mean when you say this is not as performant?

---

<div class="post-metadata">

**Author:** ![mohamed82008](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mohamed82008/32/18171_2.png) [@mohamed82008](https://discourse.julialang.org/u/mohamed82008)\
**Post date:** [August 28, 2018, 2:06pm UTC](https://discourse.julialang.org/t/extract-type-name-only-from-parametric-type/14188/9 "2018-08-28T14:06:08Z")

</div>

`eval` is usually frowned upon in a function cuz ya it could be anything in there and it is evaluated in global scope so

```julia
f() = eval(:(a = 1))

```

actually defines `a` outside of `f`, so it is a bit tricky to reason about when inside a function and is a sign you are doing things in a non-Julian way.

---

<div class="post-metadata">

**Author:** ![e3c6](https://avatars.discourse-cdn.com/v4/letter/e/e79b87/32.png) [@e3c6](https://discourse.julialang.org/u/e3c6)\
**Post date:** [August 28, 2018, 2:17pm UTC](https://discourse.julialang.org/t/extract-type-name-only-from-parametric-type/14188/10 "2018-08-28T14:17:30Z")

</div>

The type is not computed at compile-time.

```julia
thename(::Type{T}) where {T} = eval(nameof(T))
f(x::T) where {T} = thename(T)
@code_warntype f(2)

```

produces:

> Body:: **Any**  
> 1 ─ %1 = (Base.getfield)(Int64, :name)::Core.TypeName  
> │ %2 = (Base.getfield)(%1, :name)::Symbol  
> │ %3 = invoke Main.eval(%2::Symbol)::Any  
> └── return %3

(I highlighted the Any).

This is a big turnoff.

---

<div class="post-metadata">

**Author:** ![mauro3](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mauro3/32/292_2.png) [@mauro3](https://discourse.julialang.org/u/mauro3)\
**Post date:** [August 28, 2018, 2:26pm UTC](https://discourse.julialang.org/t/extract-type-name-only-from-parametric-type/14188/11 "2018-08-28T14:26:09Z")

</div>

Have you read the linked thread?

---

<div class="post-metadata">

**Author:** ![traktofon](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/traktofon/32/591_2.png) [@traktofon](https://discourse.julialang.org/u/traktofon)\
**Post date:** [August 28, 2018, 3:02pm UTC](https://discourse.julialang.org/t/extract-type-name-only-from-parametric-type/14188/12 "2018-08-28T15:02:40Z")

</div>

Why not:

```julia
mytype(::MyType1) = MyType1
mytype(::MyType2) = MyType2
# etc

f(x::AbstractMyType) = begin t = mytype(x); #=more code... =# end

```

Granted, it is one additional line per subtype, but not more.

---

<div class="post-metadata">

**Author:** ![mohamed82008](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mohamed82008/32/18171_2.png) [@mohamed82008](https://discourse.julialang.org/u/mohamed82008)\
**Post date:** [August 29, 2018, 1:10am UTC](https://discourse.julialang.org/t/extract-type-name-only-from-parametric-type/14188/13 "2018-08-29T01:10:15Z")

</div>

Check out Jameson’s last comment on that thread I linked for the best way to do this “non-sensical” operation according to him.

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [August 29, 2018, 8:47am UTC](https://discourse.julialang.org/t/extract-type-name-only-from-parametric-type/14188/14 "2018-08-29T08:47:13Z")

</div>

```julia
julia> struct Foo{T}
       x::T
       end

julia> Base.typename(Foo{Int64})
Foo

julia> VERSION
v"1.0.0"

```

---

<div class="post-metadata">

**Author:** ![mschauer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mschauer/32/13946_2.png) [@mschauer](https://discourse.julialang.org/u/mschauer)\
**Post date:** [August 29, 2018, 9:17am UTC](https://discourse.julialang.org/t/extract-type-name-only-from-parametric-type/14188/15 "2018-08-29T09:17:55Z")

</div>

What is wrong with handling the `Core.TypeName` in your use case?

---

<div class="post-metadata">

**Author:** ![e3c6](https://avatars.discourse-cdn.com/v4/letter/e/e79b87/32.png) [@e3c6](https://discourse.julialang.org/u/e3c6)\
**Post date:** [August 29, 2018, 11:58am UTC](https://discourse.julialang.org/t/extract-type-name-only-from-parametric-type/14188/16 "2018-08-29T11:58:16Z")

</div>

This returns `Core.TypeName`, note a `Type.

---

<div class="post-metadata">

**Author:** ![e3c6](https://avatars.discourse-cdn.com/v4/letter/e/e79b87/32.png) [@e3c6](https://discourse.julialang.org/u/e3c6)\
**Post date:** [August 29, 2018, 11:59am UTC](https://discourse.julialang.org/t/extract-type-name-only-from-parametric-type/14188/17 "2018-08-29T11:59:17Z")

</div>

I had defined methods that take a generic type parameter, such as `MyType1`, that don’t recognize `Core.TypeName`.

---

<div class="post-metadata">

**Author:** ![mschauer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mschauer/32/13946_2.png) [@mschauer](https://discourse.julialang.org/u/mschauer)\
**Post date:** [August 29, 2018, 12:00pm UTC](https://discourse.julialang.org/t/extract-type-name-only-from-parametric-type/14188/18 "2018-08-29T12:00:25Z")

</div>

Ah, got it.

---

<div class="post-metadata">

**Author:** ![mohamed82008](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mohamed82008/32/18171_2.png) [@mohamed82008](https://discourse.julialang.org/u/mohamed82008)\
**Post date:** [August 29, 2018, 12:24pm UTC](https://discourse.julialang.org/t/extract-type-name-only-from-parametric-type/14188/19 "2018-08-29T12:24:23Z")

</div>

Just in case I was not clear, I meant to use `.wrapper` and adapt the code from Jameson’s comment as follows:

```julia
name(::Type{T}) where {T} = (isempty(T.parameters) ? T : T.name.wrapper)

```

Sorry should have been more clear.

---

<div class="post-metadata">

**Author:** ![Sukera](https://avatars.discourse-cdn.com/v4/letter/s/ce7236/32.png) [@Sukera](https://discourse.julialang.org/u/Sukera)\
**Post date:** [August 29, 2018, 12:27pm UTC](https://discourse.julialang.org/t/extract-type-name-only-from-parametric-type/14188/20 "2018-08-29T12:27:10Z")

</div>

Do you mean this?

```julia
help?> Core.TypeName
  No documentation found.

  Summary
  ≡≡≡≡≡≡≡≡≡

  mutable struct Core.TypeName <: Any

  Fields
  ≡≡≡≡≡≡≡≡

  name :: Symbol
  module :: Module
  names :: Core.SimpleVector
  wrapper :: Type
  cache :: Core.SimpleVector
  linearcache :: Core.SimpleVector
  hash :: Int64
  mt :: Any

julia> Base.typename(Vector{Int})
Array

julia> typeof(ans)
Core.TypeName

julia> Base.typename(Vector{Int}).wrapper
Array

julia> typeof(ans) 
UnionAll 

```

`Core.TypeName.wrapper` seems to be what you want.

[Next page](https://discourse.julialang.org/t/extract-type-name-only-from-parametric-type/14188.md?page=2)
