Object general rules
If you want to hold a reference to a UObject through Unreal's Garbage Collection system, you have to keep a pointer to this UObject through a member variable that is flagged as UPROPERTY.
(Note): UPROPERTY(Transient) still hold a reference to that UObject but the property won't get serialize, that's it.
If your object is not a UCLASS or USTRUCT it cannot have UPROPERTY in it. It cannot hold a GC reference to a UObject through a member variable flagged UPROPERTY. See the last part of the page to fix that if you really need it.
If your object is a USTRUCT
It can have UPROPERTY in it
It cannot have UFunction in it
It can hold a GC reference to a UObject through a member variable flagged UPROPERTY as long as the instance of your UStruct is stored as well in a member variable flagged UPROPERTY to keep GC serialization in the loop as USTRUCT is not a UObject.
If your object is a UCLASS
It has to derive at some point from UObject
It can have UPROPERTY
It can have UFUNCTION as well in it
It can hold a GC reference to a UObject through a member variable flagged UPROPERTY
Native object type
If your object is not a UCLASS nor a USTRUCT but you still want to reference UObject?
If you DON'T want to hold a strong reference to the UObject so it can still get destroyed by the GC:
You can use a TWeakObjectPtr to that UObject
Remember that each time you access the value you pay the cost of checking if this UObject is still valid in the GCObjTable (ie Internal_IsValid) and might require a thread lock if the check is done outside of game thread. So DON'T USE IT IN MULTI-THREADED SCENARIO as it is a huge performance drop.
If you want to hold a reference to the UObject so it doesn't get destroyed by the GC:
Your class/struct can implement the abstract class FGCObject. This class provides common registration for garbage collection for non-UObject classes/struct.
In last resort (more specifically if you only have one or two objects to track) you can use TStrongObjectPtr
That's all folks