public static function determineType($name, $definition)
    {
        // check if we can find a more appropriate Type subclass
        if (\is_string($definition)) {
            $definition = ['type' => $definition];
        } elseif (\is_array($definition)) {
            if (!\array_key_exists('type', $definition)) {
                $definition['type'] = isset($definition['properties']) ? 'object' : 'string';
            }
        } else {
            throw new \InvalidArgumentException('Invalid datatype for $definition parameter.');
        }

        $type = $definition['type'] ?: 'null';

        if (!\in_array($type, ['', 'any'], true)) {
            if (\in_array($type, static::getStraightForwardTypes(), true)) {
                $className = \sprintf(
                    'Raml\Types\%sType',
                    StringTransformer::convertString($type, StringTransformer::UPPER_CAMEL_CASE)
                );
                \assert(\class_exists($className));

                return \forward_static_call_array([$className, 'createFromArray'], [$name, $definition]);
            }
            // if $type contains a '|' we can safely assume it's a combination of types (union)
            if (\strpos($type, '|') !== false) {
                return UnionType::createFromArray($name, $definition);
            }
            // if $type contains a '[]' it means we have an array with a item restriction
            if (\strpos($type, '[]') !== false) {
                return ArrayType::createFromArray($name, $definition);
            }
            // no standard type found so this must be a reference to a custom defined type
            // since the actual definition can be defined later then when it is referenced
            // we create a proxy object for lazy loading when it is needed
            return LazyProxyType::createFromArray($name, $definition);
        }

        // No subclass found, let's use base class
        return Type::createFromArray($name, $definition);
    }