Blender 2.8 - Field property declaration and dynamic class creation
The annotations for an object (which can be a class or a function as well) are stored in its __annotations__ property, as defined by PEP 526 and introduced in Python 3.6. This gives rise to the following solution:

The following approach works as I suspect you're looking for:

&gt;&gt;&gt; clss = type('TestPropGrp2', (bpy.types.PropertyGroup,), {
...     '__annotations__': {'myProp': (StringProperty, {'default': 'MyStr'})}
... })
&gt;&gt;&gt; print(clss.__annotations__)
{'myProp': (&lt;built-in function StringProperty&gt;, {'default': 'MyStr'})}


This also allows you to see that your proposed "one way to do it" approach doesn't actually work as intended:

&gt;&gt;&gt; clss = type('TestPropGrp', (bpy.types.PropertyGroup,), {})
&gt;&gt;&gt; clss.myProp : StringProperty(default='MyStr')
&gt;&gt;&gt; print(clss.__annotations__)
Traceback (most recent call last):
  File "&lt;blender_console&gt;", line 1, in &lt;module&gt;
AttributeError: type object 'TestPropGrp' has no attribute '__annotations__'