I am struggling to find the right design due to the shear amount of possibilities, so I need help

Given a type `FooID`

, which is a simple number with a bit of additional convenience attributes (I added that to to show that I cannot do a simple type alias to `Int32`

):

```
struct FooID
value::Int32
q1::Int8
q2::Int8
q3::Int8
function FooID(value)
d = digits(abs(value), pad=3)
return new(value, d[1], d[2], d[3])
end
end
```

This type is now used as field type in

```
struct Bar
fooid::FooID
end
```

Now I need to define a ton of functions which take either `FooID`

, `Bar`

or even a simple `Integer`

. I tried different ways to provide a general API and this is the best solution I have found so far:

```
convert(::Type{FooID}, bar::Bar) = bar.fooid
convert(::Type{FooID}, x::Integer) = FooID(x)
function isvalid(x)
x = convert(FooID, x)
x.fooid.q1 == 1
end
function hasfuture(x)
x = convert(FooID, x)
x.fooid.q1 > 2
end
```

This works, but I have to repeat that `convert`

line everywhere. I also tried `promote`

, `promote_rule`

and `Union`

things, but I would like to keep the API clear and understandable and could not find a better way yet.

The first idea was to define

```
hasfuture(x::FooID)
```

and then implement `prmote_rule`

to do the automatic conversion when a user falls it with `Bar`

, but I don’t like that since it does not clearly communicate that it also accepts a `Bar`

.

Another approach is to define

```
hasfuture(x::Union{FooID, Bar, Integer})
```

but that also doesn’t feel right either.

I also thought about using a type hierarchy and introduce an `AbstractFooID`

where everything derives from, but of course `Integer`

will still be a special case…

Is there a more Julian approach to this?