Advanced Type Inference Engine in TypeScript
This challenge asks you to build a simplified, yet powerful, type inference engine for TypeScript. Type inference is a core feature of TypeScript that automatically determines the types of variables and expressions, reducing boilerplate and improving code readability. Your engine will focus on inferring types within a limited scope of expressions, demonstrating the fundamental principles behind this process.
Problem Description
You are tasked with creating a function inferType that takes a TypeScript expression (represented as a string) and attempts to infer its type. The engine should handle basic arithmetic operations, variable assignments, and function calls with simple argument types. The goal is to produce a TypeScript type string that accurately reflects the inferred type of the expression. The engine should prioritize accuracy and handle common edge cases gracefully.
Key Requirements:
- Expression Parsing: The input is a string representing a TypeScript expression. You don't need to build a full-fledged parser, but the engine should be able to understand basic syntax.
- Type Inference: Infer the type of the expression based on its structure and the types of its operands.
- Type Representation: Represent the inferred type as a TypeScript type string (e.g., "number", "string", "boolean", "any", "Function", "Array<number>").
- Variable Assignment: Infer the type of a variable based on the type of the value it's assigned.
- Arithmetic Operations: Infer the type of the result of arithmetic operations (+, -, *, /) based on the types of the operands (both should be number, result is number).
- Function Calls (Simple): If a function call is encountered, assume the function always returns a
number. (This is a simplification for this challenge). - Error Handling: If the expression is invalid or the type cannot be inferred, return the string "any".
Expected Behavior:
The inferType function should return a string representing the inferred TypeScript type.
Edge Cases to Consider:
- Empty expressions.
- Expressions with invalid syntax.
- Expressions involving variables that are not assigned a value (return "any").
- Expressions with complex types (beyond the scope of this simplified engine).
- Expressions with implicit
anytypes (e.g., usingMath.random()).
Examples
Example 1:
Input: "1 + 2"
Output: "number"
Explanation: The expression is a simple addition of two numbers, resulting in a number.
Example 2:
Input: "let x = 5"
Output: "number"
Explanation: The variable 'x' is assigned the number 5, so its type is inferred as number.
Example 3:
Input: "Math.random()"
Output: "number"
Explanation: Math.random() returns a number.
Example 4:
Input: "let y = 'hello'"
Output: "string"
Explanation: The variable 'y' is assigned the string 'hello', so its type is inferred as string.
Example 5:
Input: "let z = true"
Output: "boolean"
Explanation: The variable 'z' is assigned the boolean value true, so its type is inferred as boolean.
Example 6:
Input: "let a = [1, 2, 3]"
Output: "any"
Explanation: Array types are beyond the scope of this simplified engine.
Example 7:
Input: "let b"
Output: "any"
Explanation: Variable 'b' is not assigned a value, so its type is 'any'.
Constraints
- Input Length: The input expression string will be no longer than 256 characters.
- Supported Operations: Only
+,-,*,/are supported for arithmetic operations. - Variable Names: Variable names will consist of lowercase letters only.
- Performance: The inference engine should complete within 100ms for any valid input.
- No External Libraries: You are not allowed to use external libraries for parsing or type inference.
Notes
- This is a simplified type inference engine. Do not attempt to implement a full-fledged TypeScript type system.
- Focus on handling the core concepts of type inference for basic expressions.
- Consider using regular expressions or simple string manipulation techniques to parse the expression.
- Prioritize correctness and clarity over complex optimizations.
- The "any" type is a fallback when the type cannot be determined.
- Assume that all literals (numbers, strings, booleans) are valid.
- The function call simplification means you don't need to analyze function signatures or argument types. Just assume they return a number.