As per my comment, VBA exposes a private Type, just like it exposes a Private Enum.
VBA assumes you can make use of the TypeInfo in the consuming context, but it won't allow you to declare or create instances of those types or enums.
This C++ answer is partly informative:
Access Control is applied to names
The access specifier for the name has nothing to do with it's type
But it's perhaps useful to think of a Private Type in a standard module, as something like a "PublicNotCreatable" class. If you provide a public wrapper, then the type is accessible outside the host module.
But VBA handles things differently when the Type is in a Public Class Module!
Here's your Module1
expanded:
Option Explicit
Private Type TSomething
Foo As Integer
Bar As Integer
End Type
Public Type TOtherThing
Foo As Integer
Bar As Integer
End Type
Public Type TWrapperThing
Something As TSomething
End Type
Public Something As TSomething
Public Otherthing As TOtherThing
Public Wrapperthing As TWrapperThing
Public Function GetSomething() As TSomething
GetSomething.Foo = 1
End Function
Public Function GetOtherthing() As TOtherThing
GetOtherthing.Foo = 1
End Function
And Module2
expanded:
Option Explicit
Sub DoThings()
'Compile Error: User-defined type not defined
'Dim oSomething As TSomething
Dim vSomething As Variant
Dim oOtherthing As Module1.TOtherThing
Dim vOtherthing As Variant
Dim oWrapperthing As Module1.TWrapperThing
Module1.Something.Foo = 42
Module1.Otherthing.Foo = 42
Module1.Wrapperthing.Something.Foo = 42
'Compile Error: Only user-defined types defined in public object modules can be coerced to or from a variant or passed to late-bound functions
'vSomething = Module1.Something
'vOtherthing = Module1.Otherthing
oOtherthing = Module1.Otherthing
oOtherthing.Foo = 43
'Is 43 > 42?
Debug.Assert oOtherthing.Foo > Module1.Otherthing.Foo
'Compile Errors: "GetSomething" User-defined type not defined
'Module1.GetSomething.Foo = 42
'Module1.GetSomething().Foo = 42
Module1.GetOtherthing.Foo = 42
Module1.GetOtherthing().Foo = 42
End Sub
Module1.TSomething
and assign that toModule1.Something
? – BarretoPrivate
access modifier as far as using a type goes - and happily lets you "leak" private types to an interface, even though the client code doesn't know about the type involved, yet it does know enough to use it, but isn't allowed to declare variables of that type... but runtime will happily dump it into aVariant
... I need a drink. – JakobaIDispatch
andIUnknown
. It would appear that the compiler is accessingModule1.Something
by treating it as an Object instead of a Namespace, then querying the interface to see if it can successfully callSomething.Bar
.Something
is exposed by beingPublic
, so it doesn't need access to the type - it queries it's interface to see if it supports the propertyBar
. Note that without doing this (kind of like duck typing), late binding would be much more difficult. – TeakDebug.Print TypeName(Module1.Something)
provides an additional clue that COM is examining the interfaces - the error it produces is (my emphasis) "Only user-defined types defined in public object modules can be coerced to or from a variant or passed to late-bound functions".Debug.Print TypeName(Module1.Something.Bar)
happily spits out "Integer". – Teak