Row Polymorphism in TypeScript
Row polymorphism allows you to treat objects with different types as if they share a common structure, enabling more flexible and reusable code. This challenge asks you to implement a system that allows you to work with a collection of objects, each potentially having a different set of properties, but all conforming to a defined "row" structure. This is particularly useful when dealing with data from various sources or APIs where the schema might not be entirely consistent.
Problem Description
You need to create a TypeScript system that enables row polymorphism. This system should allow you to define a base "row" type and then create multiple specific types that extend this base type with additional properties. The core functionality should be a function that accepts an array of these polymorphic row objects and processes them in a way that respects their individual types.
Specifically, you need to:
- Define a Base Row Type: Create a type called
BaseRowwith a common propertyid: string. - Define Specific Row Types: Create at least three specific row types (
RowTypeA,RowTypeB,RowTypeC) that extendBaseRow. Each of these types should have unique properties in addition to theidproperty. For example:RowTypeA:id: string, name: stringRowTypeB:id: string, age: numberRowTypeC:id: string, city: string, country: string
- Create a Polymorphic Row Type: Define a type
PolymorphicRowthat represents a union of all the specific row types (includingBaseRowif it's not already implicitly included). - Implement a Processing Function: Create a function called
processRowsthat accepts an array ofPolymorphicRowobjects. This function should iterate through the array and, for each row, perform a type-specific action based on its type. The actions should be:- If the row is
RowTypeA, log "Processing RowTypeA: {name}". - If the row is
RowTypeB, log "Processing RowTypeB: {age}". - If the row is
RowTypeC, log "Processing RowTypeC: {city}, {country}". - If the row is
BaseRow(and not one of the specific types), log "Processing BaseRow: {id}".
- If the row is
Examples
Example 1:
Input: [
{ id: "1", name: "Alice" },
{ id: "2", age: 30 },
{ id: "3", city: "New York", country: "USA" },
{ id: "4" }
]
Output:
"Processing RowTypeA: {name}"
"Processing RowTypeB: {age}"
"Processing RowTypeC: {city}, {country}"
"Processing BaseRow: {id}"
Explanation: The `processRows` function iterates through the array, identifies the type of each object, and logs the appropriate message based on its type.
Example 2:
Input: [
{ id: "5", name: "Bob" },
{ id: "6" }
]
Output:
"Processing RowTypeA: {name}"
"Processing BaseRow: {id}"
Explanation: Only the first object has the `name` property, so only it is processed as `RowTypeA`. The second object only has the `id` property, so it's processed as `BaseRow`.
Example 3: (Edge Case - Empty Array)
Input: []
Output: (No output)
Explanation: The `processRows` function should handle an empty array gracefully without errors.
Constraints
- The input array to
processRowscan contain a mix ofRowTypeA,RowTypeB,RowTypeC, andBaseRowobjects. - The
idproperty is always present in all row types. - The
processRowsfunction should not throw errors if it encounters an unexpected row type (though handling it gracefully is preferred). - The solution should be type-safe and leverage TypeScript's type system effectively.
Notes
- Consider using type guards (e.g.,
isRowTypeA,isRowTypeB,isRowTypeC) to determine the type of each row within theprocessRowsfunction. These guards can be implemented usinginoperator checks. - The goal is to demonstrate an understanding of TypeScript's type system and how to work with union types and type guards to achieve row polymorphism.
- Focus on clarity and readability in your code. Well-commented code is appreciated.
- While performance isn't a primary concern for this challenge, avoid unnecessarily complex or inefficient solutions.