Beyond Uniformity: Creating Flexible Arrays in TypeScript
Union Types:
Imagine a shopping list. It can have fruits (strings), quantities (numbers), or both. In TypeScript, you can define a union type that combines multiple data types. Here's how:
let shoppingList: (string | number)[] = ["apple", 2, "bananas"];
This declares an array
shoppingList
that can hold strings (like "apple") or numbers (like 2). The|
symbol represents the union between the types.Tuples:
Tuples are a special kind of array where the order and types of elements are fixed. They're useful when you know exactly what kind of data each position in the array will hold. For instance, a tuple representing a person might have a name (string) and age (number).
type Person = [string, number]; let person1: Person = ["Alice", 30];
Here, we define a type
Person
as a tuple containing a string and a number. Then, we create an arrayperson1
of typePerson
.
Choosing the right approach:
- Use union types if your array can hold a variety of different data types at any position.
- Use tuples if the order and types of elements matter in your array.
// Shopping list with strings (fruits) and numbers (quantities)
let shoppingList: (string | number)[] = ["apple", 2, "bananas"];
console.log(shoppingList[0]); // Output: "apple" (string)
console.log(shoppingList[1]); // Output: 2 (number)
// This would cause an error because "boolean" isn't part of the union
// shoppingList[2] = true;
// Person tuple with name (string) and age (number)
type Person = [string, number];
let person1: Person = ["Alice", 30];
console.log(person1[0]); // Output: "Alice" (string)
console.log(person1[1]); // Output: 30 (number)
// This would cause an error because the order is wrong
// let person2: Person = [30, "Bob"];
// This would also cause an error because "boolean" isn't allowed
// let person3: Person = ["Charlie", true];
Generics:
Generics allow you to create arrays that can hold any type, but with a twist. You define a placeholder type within square brackets (
<T>
) when creating the array type. This placeholder can then be used throughout the code to represent the actual data type stored in the array.Here's a basic example:
function identity<T>(arr: T[]): T[] { return arr; } let numberArray: number[] = [1, 2, 3]; let stringArray: string[] = ["hello", "world"]; console.log(identity(numberArray)); // Output: [1, 2, 3] console.log(identity(stringArray)); // Output: ["hello", "world"]
In this example, the
identity
function takes an array of any typeT
and returns it back. This allows for flexibility, but you lose some type safety compared to union types or tuples.Type Assertions (Less preferred):
Type assertions are a way to tell the TypeScript compiler to treat a value as a specific type, even if the compiler might have inferred a different type. This can be useful in specific scenarios, but it's generally recommended to avoid them as they can bypass type safety checks.
let unknownArray: any[] = [1, "hello", true]; // Type assertion (not recommended for frequent use) let numberElement = unknownArray[0] as number; console.log(numberElement * 2); // Output: 2 // This could throw an error at runtime if the assertion is wrong let stringElement = unknownArray[1] as string; console.log(stringElement.toUpperCase());
arrays typescript