i think you mean void pointers. the callee will then cast those pointers to an actual type it knows about (and then possibly go horribly wrong)
What's inside a T? How can we make one? We don't know, but that's fine since we have been provided with APIs which give us a pointer-to-T and which take a pointer-to-T so it delivers the opacity required.
What if you're providing an API header to an otherwise closed-source binary and you don't want to expose the struct definition?
How would the compiler know the size and alignment required for struct Foo if it never gets to see its definition?