diff --git a/modules/gdscript/gdscript_analyzer.cpp b/modules/gdscript/gdscript_analyzer.cpp
index e925350ba33..d6a2c35ae86 100644
--- a/modules/gdscript/gdscript_analyzer.cpp
+++ b/modules/gdscript/gdscript_analyzer.cpp
@@ -432,8 +432,28 @@ GDScriptParser::DataType GDScriptAnalyzer::resolve_datatype(GDScriptParser::Type
 					case GDScriptParser::ClassNode::Member::CONSTANT:
 						if (member.constant->get_datatype().is_meta_type) {
 							result = member.constant->get_datatype();
+							result.is_meta_type = false;
 							found = true;
 							break;
+						} else if (Ref<Script>(member.constant->initializer->reduced_value).is_valid()) {
+							Ref<GDScript> gdscript = member.constant->initializer->reduced_value;
+							if (gdscript.is_valid()) {
+								Ref<GDScriptParserRef> ref = get_parser_for(gdscript->get_path());
+								if (ref->raise_status(GDScriptParserRef::INTERFACE_SOLVED) != OK) {
+									push_error(vformat(R"(Could not parse script from "%s".)", gdscript->get_path()), p_type);
+									return GDScriptParser::DataType();
+								}
+								result = ref->get_parser()->head->get_datatype();
+								result.is_meta_type = false;
+							} else {
+								Ref<GDScript> script = member.constant->initializer->reduced_value;
+								result.kind = GDScriptParser::DataType::SCRIPT;
+								result.builtin_type = Variant::OBJECT;
+								result.script_type = script;
+								result.script_path = script->get_path();
+								result.native_type = script->get_instance_base_type();
+							}
+							break;
 						}
 						[[fallthrough]];
 					default:
@@ -2129,6 +2149,9 @@ void GDScriptAnalyzer::reduce_call(GDScriptParser::CallNode *p_call, bool is_awa
 
 		if (is_self && parser->current_function != nullptr && parser->current_function->is_static && !is_static) {
 			push_error(vformat(R"*(Cannot call non-static function "%s()" from static function "%s()".)*", p_call->function_name, parser->current_function->identifier->name), p_call->callee);
+		} else if (!is_self && base_type.is_meta_type && !is_static) {
+			base_type.is_meta_type = false; // For `to_string()`.
+			push_error(vformat(R"*(Cannot call non-static function "%s()" on the class "%s" directly. Make an instance instead.)*", p_call->function_name, base_type.to_string()), p_call->callee);
 		} else if (is_self && !is_static && !lambda_stack.is_empty()) {
 			push_error(vformat(R"*(Cannot call non-static function "%s()" from a lambda function.)*", p_call->function_name), p_call->callee);
 		}
@@ -2392,6 +2415,11 @@ void GDScriptAnalyzer::reduce_identifier_from_base(GDScriptParser::IdentifierNod
 					resolve_function_signature(member.function);
 					p_identifier->set_datatype(make_callable_type(member.function->info));
 					break;
+				case GDScriptParser::ClassNode::Member::CLASS:
+					// For out-of-order resolution:
+					resolve_class_interface(member.m_class);
+					p_identifier->set_datatype(member.m_class->get_datatype());
+					break;
 				default:
 					break; // Type already set.
 			}
@@ -3257,6 +3285,7 @@ bool GDScriptAnalyzer::get_function_signature(GDScriptParser::Node *p_source, GD
 			}
 		}
 		r_return_type = found_function->get_datatype();
+		r_return_type.is_meta_type = false;
 		r_return_type.is_coroutine = found_function->is_coroutine;
 
 		return true;
diff --git a/modules/gdscript/tests/scripts/analyzer/features/gdscript_to_preload.gd b/modules/gdscript/tests/scripts/analyzer/features/gdscript_to_preload.gd
new file mode 100644
index 00000000000..fb0ace6a90a
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/gdscript_to_preload.gd
@@ -0,0 +1,5 @@
+func test():
+	pass
+
+func something():
+	return "OK"
diff --git a/modules/gdscript/tests/scripts/analyzer/features/gdscript_to_preload.out b/modules/gdscript/tests/scripts/analyzer/features/gdscript_to_preload.out
new file mode 100644
index 00000000000..d73c5eb7cde
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/gdscript_to_preload.out
@@ -0,0 +1 @@
+GDTEST_OK
diff --git a/modules/gdscript/tests/scripts/analyzer/features/inner_class_as_return_type.gd b/modules/gdscript/tests/scripts/analyzer/features/inner_class_as_return_type.gd
new file mode 100644
index 00000000000..4f4b7a48975
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/inner_class_as_return_type.gd
@@ -0,0 +1,11 @@
+class InnerClass:
+	var val := "OK"
+	static func create_instance() -> InnerClass:
+		return new()
+
+func create_inner_instance() -> InnerClass:
+	return InnerClass.create_instance()
+
+func test():
+	var instance = create_inner_instance()
+	print(instance.val)
diff --git a/modules/gdscript/tests/scripts/analyzer/features/inner_class_as_return_type.out b/modules/gdscript/tests/scripts/analyzer/features/inner_class_as_return_type.out
new file mode 100644
index 00000000000..1ccb591560d
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/inner_class_as_return_type.out
@@ -0,0 +1,2 @@
+GDTEST_OK
+OK
diff --git a/modules/gdscript/tests/scripts/analyzer/features/use_preload_script_as_type.gd b/modules/gdscript/tests/scripts/analyzer/features/use_preload_script_as_type.gd
new file mode 100644
index 00000000000..5f73064cc08
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/use_preload_script_as_type.gd
@@ -0,0 +1,5 @@
+const preloaded : GDScript = preload("gdscript_to_preload.gd")
+
+func test():
+	var preloaded_instance: preloaded = preloaded.new()
+	print(preloaded_instance.something())
diff --git a/modules/gdscript/tests/scripts/analyzer/features/use_preload_script_as_type.out b/modules/gdscript/tests/scripts/analyzer/features/use_preload_script_as_type.out
new file mode 100644
index 00000000000..1ccb591560d
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/use_preload_script_as_type.out
@@ -0,0 +1,2 @@
+GDTEST_OK
+OK