With macros you can start by observing the AST generated with `dumpTree` or `dumpAstGen`.
So start with : import std/[macros] dumpTree: type Person* = object name*: string job*: string email*: string Run This will output the following : StmtList TypeSection TypeDef Postfix Ident "*" Ident "Person" Empty ObjectTy Empty Empty RecList IdentDefs Postfix Ident "*" Ident "name" Ident "string" Empty IdentDefs Postfix Ident "*" Ident "job" Ident "string" Empty IdentDefs Postfix Ident "*" Ident "email" Ident "string" Empty Run This gives you the AST in a tree readable format. Now do the same with `dumpAstGen` this gives you the output in "macro compatible" format : nnkStmtList.newTree( nnkTypeSection.newTree( nnkTypeDef.newTree( nnkPostfix.newTree( newIdentNode("*"), newIdentNode("Person") ), newEmptyNode(), nnkObjectTy.newTree( newEmptyNode(), newEmptyNode(), nnkRecList.newTree( nnkIdentDefs.newTree( nnkPostfix.newTree( newIdentNode("*"), newIdentNode("name") ), newIdentNode("string"), newEmptyNode() ), nnkIdentDefs.newTree( nnkPostfix.newTree( newIdentNode("*"), newIdentNode("job") ), newIdentNode("string"), newEmptyNode() ), nnkIdentDefs.newTree( nnkPostfix.newTree( newIdentNode("*"), newIdentNode("email") ), newIdentNode("string"), newEmptyNode() ) ) ) ) ) ) Run This is the output. Now use that out to construct your macro ; mostly we need to change the object type ident name and the fields. What I will do is construct the `nnkRecList.newTree` separetely because I want to iterate to build it and then replace the name of the type by the argument in `newIdentNode("Person")` . This is the outcome : import std/[macros] dumpAstGen: type Person* = object name*: string job*: string email*: string macro buildType(typName: untyped, fieldNames: varargs[untyped]) : untyped = # First construct the AST based on varargs var fieldsAst = nnkRecList.newTree() for f in fieldNames: fieldsAst.add nnkIdentDefs.newTree( # postfix is the * in the field nnkPostFix.newTree( newIDentNode("*"), newIdentNode(strVal(f)) ), # This assume all the fields are string newIdentNode("string"), newEmptyNode() ) result = nnkStmtList.newTree( nnkTypeSection.newTree( nnkTypeDef.newTree( nnkPostfix.newTree( newIdentNode("*"), newIdentNode(strVal(typName)) ), newEmptyNode(), nnkObjectTy.newTree( newEmptyNode(), newEmptyNode(), # Replace the specific AST with a generic one : fieldsAst ) ) ) ) echo result.repr # Check it works buildType(Person, name, job, email) var alice = Person(name: "Alice", job: "Dev", email: "f...@bar.com") echo alice buildType(Animal, name, species, toy) var bob = Animal(name: "Bob", species: "dog", toy: "ball") echo bob Run