> The accessor are only visible for the internal library proc but not exported > outside of the library.
In this case I cannot rely on hiding the fields via re-exporting, because the library is by design supposed to be extended on user side. Think of an UI component library, where users should be able to define their own components. @lscrd Good points about the runtime checks, but yes compile time security would be preferred. I have now found two solutions that seem to satisfy the requirements: 1\. Macro solution: # on lib side template privateInitializer(element: typed, idString: string): untyped = element.id = idString element macro newElement*(T: typedesc, id: string, args: varargs[untyped]): untyped = # convert varargs into an object constructor call of T let constructor = newTree(nnkObjConstr) constructor.add(T.getTypeInst[1]) for arg in args: expectKind(arg, nnkExprEqExpr) constructor.add(newColonExpr(arg[0], arg[1])) # apply post construction initialization of parent fields result = newCall(bindSym"privateInitializer", constructor, id) # on user side newElement(ElementA, id="A", a=1) Run 2\. Template solution with an explicit check that only object constructors are passed in: # on lib side macro verifyObjectConstructor(x: typed): untyped = if x.kind != nnkObjConstr: error($x.repr[0..^1] & " is not an object constructor") template newElement*(idString: string, constructor: typed): untyped = verifyObjectConstructor(constructor) let element = constructor element.id = idString element # on user side newElement("A", ElementA(a: 1)) # abusing the template as an arbitrary setter is now a compile time error: let el = ElementA(a: 1) newElement("A", el) Run @Araq: What is your opinion on this? I'm wondering if it would make sense to differentiate visibility for construction vs field access. As far as I can see a lot of visibility problems would be solved if there was an intermediate between fully-hidden and fully-exposed which is "exposed in object construction". Would it for instance make sense to have type Element* = ref object of RootObj id {.initializable.}: string Run so that public access to `id` is prevented in general, but `id` can be passed into the constructor including subtype constructors?