@xflywind in your simple example, you could use
[concepts](https://nim-lang.org/docs/manual_experimental.html#concepts) like so:
type
Animal* = concept a
a.id is int
a.sleep()
a.bark(int, int) is string
a.dance(string) is string
People*[T] = object
pet: T
# User defined type
Dog* = object
id: int
# User defined procs
proc sleep*(d: Dog) =
discard
proc bark*(d: Dog, b: int, c: int): string =
result = $(d.id + b + c)
proc dance*(d: Dog, b: string): string =
result = b
proc newDog*(id: int): Dog =
result.id = 1314
let people = People[Dog](pet: newDog(12))
doAssert people.pet.bark(12, 14) == "1340"
doAssert people.pet.dance("dancing") == "dancing"
Run