Gradual Typing System in TypeScript
This challenge asks you to implement a simplified gradual typing system in TypeScript. Gradual typing allows you to mix dynamically typed and statically typed code within the same project, providing flexibility during development while still benefiting from type safety where desired. Your task is to create a system that allows you to annotate variables with optional type information, and then dynamically check these annotations at runtime.
Problem Description
You need to build a function gradualTypeCheck that takes an object as input. This object represents a set of variables, each potentially annotated with a type. The function should perform runtime type checks based on these annotations.
What needs to be achieved:
- Create a function
gradualTypeCheckthat accepts an object containing variables and their optional type annotations. - Dynamically check the type of each variable against its annotation (if present).
- Return a boolean indicating whether all type checks passed.
- Handle cases where a variable has no type annotation (treat as dynamically typed - no check needed).
- Handle type mismatches gracefully, returning
falseif any check fails.
Key Requirements:
- The input object will have keys representing variable names.
- Each value in the input object will be either:
- A value of any type (e.g., number, string, boolean, object, array).
- An object with a
valueproperty (the variable's value) and atypeproperty (a string representing the expected type). Valid type strings are:"number","string","boolean","object","array".
- The type checking should be performed at runtime.
- The function should not throw errors; it should return
falseon type mismatches.
Expected Behavior:
The gradualTypeCheck function should iterate through the input object. For each variable:
- If the variable has a
typeannotation, it should perform a runtime type check usingtypeoforArray.isArray()(for arrays) to verify that the variable's value matches the specified type. - If the variable does not have a
typeannotation, it should skip the type check. - If any type check fails, the function should immediately return
false. - If all type checks pass (or if there are no type annotations), the function should return
true.
Edge Cases to Consider:
- Empty input object.
- Variables with
nullorundefinedvalues. - Arrays containing mixed types (should be considered a mismatch if the type annotation is "array").
- Objects with properties of different types (should be considered a mismatch if the type annotation is "object").
- Invalid type strings in the
typeannotation (should be treated as dynamically typed - no check needed).
Examples
Example 1:
Input: {
name: "Alice",
age: 30,
isStudent: false,
grades: [90, 85, 95]
}
Output: true
Explanation: No type annotations are present, so no checks are performed.
Example 2:
Input: {
name: "Bob",
age: "25",
isStudent: true,
grades: [80, 75, "90"]
}
Output: false
Explanation: `age` is annotated as "number" but its value is a string. `grades` is annotated as "array" but contains a string.
Example 3:
Input: {
name: { firstName: "Charlie", lastName: "Brown" },
age: 20,
isStudent: false,
grades: [70, 80, 90],
address: { street: "123 Main St", city: "Anytown" },
}
Output: false
Explanation: `name` is annotated as "string" but its value is an object. `address` is annotated as "object" but its value is an object.
Example 4:
Input: {
x: 10,
y: "hello",
z: true,
w: [1, 2, 3],
a: { a: 1, b: 2 },
b: null
}
Output: false
Explanation: 'y' is annotated as "number" but is a string. 'w' is annotated as "string" but is an array. 'a' is annotated as "number" but is an object.
Constraints
- The input object will contain at most 100 variables.
- Type annotation strings will be one of:
"number","string","boolean","object","array". - Variable values can be of any valid JavaScript type.
- The function must return a boolean value.
Notes
- Consider using
typeoffor primitive types (number, string, boolean). - Use
Array.isArray()to check if a variable is an array. - For objects, you can perform a simple check to see if the value is an object using
typeof value === 'object' && value !== null. A more robust check would involve verifying the types of the object's properties, but this is beyond the scope of this challenge. - Focus on the core logic of runtime type checking. Error handling beyond returning
falseon mismatch is not required. - Think about how to handle cases where the
typeannotation is invalid. Treating them as dynamically typed is a reasonable approach.