Type System & Safety
Harneet features a robust and comprehensive type system designed to ensure code correctness and prevent runtime errors through static analysis.
Comprehensive Type Checking
-
Static Type Analysis: Harneet performs complete type checking during the parsing phase, catching type-related errors before runtime.
1 2 3 4
```harneet // Example: Type mismatch caught at compile time var num int = "hello" // Error: Cannot assign string to int ``` -
Function Parameter Validation: Automatic type checking ensures that function calls provide arguments matching the declared parameter types, with detailed error messages for mismatches.
1 2 3 4 5 6
```harneet function add(a int, b int) int { return a + b } var result = add(10, "hello") // Error: Argument 'hello' (string) cannot be assigned to parameter 'b' (int) ``` -
Variable Type Declarations: Explicit type annotations (e.g.,
var x int = 42) allow for compile-time validation, ensuring type consistency.1 2 3 4
```harneet var age int = 30 // var age string = "thirty" // Error: Cannot re-declare 'age' with a different type ``` -
Return Type Validation: Functions must return values that match their declared return types.
1 2 3 4 5
```harneet function getNumber() int { return "hello" // Error: Function declared to return int, but returning string } ``` -
Array Type Consistency: Arrays can be type-safe (e.g.,
int[],string[],bool[]), with validation of element types.1 2 3 4
```harneet var numbers = [1, 2, 3] // Inferred as int[] // numbers = [1, "hello"] // Error: Cannot assign string to int[] array ``` -
Advanced Type Inference: The language features sophisticated type inference for expressions, arrays, and function calls, reducing the need for explicit type declarations.
1 2 3 4 5
```harneet var inferredNum = 10 // inferred as int var inferredStr = "Harneet" // inferred as string var inferredBool = true // inferred as bool ``` -
Type Compatibility: Smart type compatibility rules are applied for numeric types and safe conversions.
1 2 3 4 5
```harneet var intVal int = 10 var floatVal float64 = intVal // int can be assigned to float64 // var anotherInt int = floatVal // Error: float64 cannot be assigned to int without explicit conversion ``` -
Enhanced Error Messages: Detailed error messages provide helpful suggestions and precise locations for type-related issues.
1 2 3 4 5 6
```harneet // Example of an enhanced error message // Calling a function with wrong argument type might produce: // Error: Argument 'hello' (string) cannot be assigned to parameter 'b' (int) in function 'add' at line 5, column 12. // Suggestion: Ensure argument type matches parameter type. ``` -
Zero Runtime Type Errors: Static analysis aims to prevent type-related errors from occurring at runtime.
1 2 3 4
```harneet // Because of static analysis, code like this will not even run: // var x int = "abc" // Caught at compile time, preventing runtime crash ``` -
Zero Value Type Safety: All declared variables automatically receive appropriate zero values for their respective types, ensuring predictable behavior.
1 2 3 4 5
```harneet var defaultInt int // defaultInt is 0 var defaultString string // defaultString is "" var defaultBool bool // defaultBool is false ```
Development Features
The type system is complemented by several development features that aid in debugging and code quality.
- REPL Support: The interactive Read-Eval-Print Loop (REPL) provides immediate feedback on type correctness during development.
- Debug Mode: A comprehensive logging system with a
-debugflag helps in tracing type-related issues. - Stack Traces: Detailed error traces with source locations provide context for type errors.
- Import Analysis: The system detects unused and duplicate imports, promoting cleaner code.
- Error Suggestions: Helpful error messages often include suggestions for fixing type-related problems.
The any Type
Harneet supports the any type as a top type (supertype of all types) with strict, one-way assignability rules. This design preserves Harneet's strong typing while enabling flexibility at dynamic boundaries like JSON, OS, regex, and external APIs.
Strict Assignability Rules
The any type follows these strict rules:
- T → any (Upcast): ✅ ALLOWED - Any concrete type can be assigned to
any - any → T (Downcast): ❌ FORBIDDEN - Requires explicit cast using the
castmodule
This one-way assignability prevents type safety violations while allowing flexibility where needed.
When to Use any
✅ Good Use Cases:
-
JSON Parsing - Dynamic JSON data
-
External APIs - Heterogeneous system data
-
Configuration - Dynamic config values
-
Generic Utilities - Flexible helper functions
❌ Avoid Using any:
- Internal business logic - Use precise types
- Public APIs - Prefer concrete types for clarity
- Data structures - Use typed collections
Explicit Narrowing
The cast module provides type-safe narrowing from any to concrete types:
Available Cast Functions: - cast.ToInt(any) - Convert to integer - cast.ToString(any) - Convert to string - cast.ToBool(any) - Convert to boolean - cast.ToFloat(any) - Convert to float - cast.ToArray(any) - Convert to array - cast.ToMap(any) - Convert to map - cast.CanCast(any, type) - Check if conversion is possible
Best Practices
Early Narrowing Pattern (Recommended):
Type Guard Pattern:
Type Safety Guarantees
The any type maintains Harneet's strong type safety through:
- Compile-Time Enforcement - Cannot assign
anyto concrete types without explicit cast - Runtime Validation - Cast functions validate conversions and return errors
- No Implicit Conversions - All narrowing must be explicit
- Clear Error Messages - Detailed feedback when conversions fail
| Error Messages | |
|---|---|
Zero Values System
Harneet automatically initializes all declared variables to their "zero value" if no explicit value is provided. This ensures that variables always have a defined state.
Multiple Assignment Examples
The type system works seamlessly with multiple assignment, ensuring type safety even when multiple values are returned or assigned.