diff --git a/src/main/java/noppes/npcs/client/gui/util/script/interpreter/ScriptDocument.java b/src/main/java/noppes/npcs/client/gui/util/script/interpreter/ScriptDocument.java index d6efd73f7..04777d514 100644 --- a/src/main/java/noppes/npcs/client/gui/util/script/interpreter/ScriptDocument.java +++ b/src/main/java/noppes/npcs/client/gui/util/script/interpreter/ScriptDocument.java @@ -992,7 +992,8 @@ public class ScriptDocument { typeInfo = resolveExpressionType(initializer.trim(), bodyStart + m.start(3)); } if (typeInfo == null) { - typeInfo = TypeInfo.fromClass(Object.class); // Default to Object for unresolved + // Use "any" type for uninitialized variables in JavaScript + typeInfo = TypeInfo.ANY; } int initStart = -1, initEnd = -1; @@ -1297,7 +1298,8 @@ public class ScriptDocument { typeInfo = resolveExpressionType(initializer.trim(), m.start(3)); } if (typeInfo == null) { - typeInfo = TypeInfo.fromClass(Object.class); + // Use "any" type for uninitialized variables in JavaScript + typeInfo = TypeInfo.ANY; } int initStart = -1, initEnd = -1; diff --git a/src/main/java/noppes/npcs/client/gui/util/script/interpreter/token/TokenType.java b/src/main/java/noppes/npcs/client/gui/util/script/interpreter/token/TokenType.java index 8ee1d0f29..c932fbfec 100644 --- a/src/main/java/noppes/npcs/client/gui/util/script/interpreter/token/TokenType.java +++ b/src/main/java/noppes/npcs/client/gui/util/script/interpreter/token/TokenType.java @@ -80,6 +80,9 @@ public enum TokenType { public static TokenType getByType(TypeInfo typeInfo) { if (typeInfo == null || !typeInfo.isResolved()) return TokenType.UNDEFINED_VAR; + + if ("any".equals(typeInfo.getFullName())) + return TokenType.KEYWORD; // Use the TypeInfo's own token type, which handles ScriptTypeInfo correctly return typeInfo.getTokenType(); diff --git a/src/main/java/noppes/npcs/client/gui/util/script/interpreter/type/TypeChecker.java b/src/main/java/noppes/npcs/client/gui/util/script/interpreter/type/TypeChecker.java index ed3a573fc..e9164f20f 100644 --- a/src/main/java/noppes/npcs/client/gui/util/script/interpreter/type/TypeChecker.java +++ b/src/main/java/noppes/npcs/client/gui/util/script/interpreter/type/TypeChecker.java @@ -18,6 +18,11 @@ public final class TypeChecker { if (expected == null) return true; // void can accept anything (shouldn't happen) if (actual == null) return true; // Can't verify, assume compatible + // Handle "any" type - universally compatible (JavaScript/TypeScript) + if ("any".equals(expected.getFullName()) || "any".equals(actual.getFullName())) { + return true; + } + // Handle null literal - null is compatible with any reference type (non-primitive) if ("".equals(actual.getFullName())) { Class expectedClass = expected.getJavaClass(); diff --git a/src/main/java/noppes/npcs/client/gui/util/script/interpreter/type/TypeInfo.java b/src/main/java/noppes/npcs/client/gui/util/script/interpreter/type/TypeInfo.java index cf4dbfd11..28f307187 100644 --- a/src/main/java/noppes/npcs/client/gui/util/script/interpreter/type/TypeInfo.java +++ b/src/main/java/noppes/npcs/client/gui/util/script/interpreter/type/TypeInfo.java @@ -36,6 +36,13 @@ public class TypeInfo { * Singleton constant for the void type. */ public static final TypeInfo VOID = fromPrimitive("void"); + + /** + * Singleton constant for the "any" type (used in JavaScript/TypeScript). + * The "any" type is universally compatible - it can be assigned to anything + * and anything can be assigned to it. + */ + public static final TypeInfo ANY = new TypeInfo("any", "any", "", Kind.CLASS, null, true, null); private final String simpleName; // e.g., "List", "ColorType" private final String fullName; // e.g., "java.util.List", "kamkeel...IOverlay$ColorType"