Introduction
TypeScript, the popular statically-typed superset of JavaScript, offers advanced type manipulation features that enhance development with strong typing. Square brackets []
serve distinct purposes in TypeScript. This post details how square brackets work in TypeScript, from array types to indexed access types and beyond.
1. Defining Array Types
Square brackets in TypeScript define array types with precision.
let let numbers: number[]
numbers: number[] = [1, 2, 3];
let let strings: string[]
strings: interface Array<T>
Array<string> = ["hello", "world"];
This syntax specifies that numbers
contains numbers, and strings
contains strings.
2. Tuple Types
Square brackets define tuples - arrays with fixed lengths and specific types at each index.
type type Point = [number, number]
Point = [number, number];
let let coordinates: Point
coordinates: type Point = [number, number]
Point = [12.34, 56.78];
In this example, Point
represents a 2D coordinate as a tuple.
3. The length
Property
Every array in TypeScript includes a length
property that the type system recognizes.
type type LengthArr<T extends Array<any>> = T["length"]
LengthArr<function (type parameter) T in type LengthArr<T extends Array<any>>
T extends interface Array<T>
Array<any>> = function (type parameter) T in type LengthArr<T extends Array<any>>
T["length"];
type type foo = 2
foo = type LengthArr<T extends Array<any>> = T["length"]
LengthArr<["1", "2"]>;
TypeScript recognizes length
as the numeric size of the array.
4. Indexed Access Types
Square brackets access specific index or property types.
type type Point = [number, number]
Point = [number, number];
type type FirstElement = number
FirstElement = type Point = [number, number]
Point[0];
Here, FirstElement
represents the first element in the Point
tuple: number
.
5. Creating Union Types from Tuples
Square brackets help create union types from tuples efficiently.
type type Statuses = ["active", "inactive", "pending"]
Statuses = ["active", "inactive", "pending"];
type type CurrentStatus = "active" | "inactive" | "pending"
CurrentStatus = type Statuses = ["active", "inactive", "pending"]
Statuses[number];
Statuses[number]
creates a union from all tuple elements.
6. Generic Array Types and Constraints
Square brackets define generic constraints and types.
function function logArrayElements<T extends any[]>(elements: T): void
logArrayElements<function (type parameter) T in logArrayElements<T extends any[]>(elements: T): void
T extends any[]>(elements: T extends any[]
elements: function (type parameter) T in logArrayElements<T extends any[]>(elements: T): void
T) {
elements: T extends any[]
elements.Array<any>.forEach(callbackfn: (value: any, index: number, array: any[]) => void, thisArg?: any): void
Performs the specified action for each element in an array.forEach(element: any
element => var console: Console
The `console` module provides a simple debugging console that is similar to the
JavaScript console mechanism provided by web browsers.
The module exports two specific components:
* A `Console` class with methods such as `console.log()`, `console.error()` and `console.warn()` that can be used to write to any Node.js stream.
* A global `console` instance configured to write to [`process.stdout`](https://nodejs.org/docs/latest-v22.x/api/process.html#processstdout) and
[`process.stderr`](https://nodejs.org/docs/latest-v22.x/api/process.html#processstderr). The global `console` can be used without importing the `node:console` module.
_**Warning**_: The global console object's methods are neither consistently
synchronous like the browser APIs they resemble, nor are they consistently
asynchronous like all other Node.js streams. See the [`note on process I/O`](https://nodejs.org/docs/latest-v22.x/api/process.html#a-note-on-process-io) for
more information.
Example using the global `console`:
```js
console.log('hello world');
// Prints: hello world, to stdout
console.log('hello %s', 'world');
// Prints: hello world, to stdout
console.error(new Error('Whoops, something bad happened'));
// Prints error message and stack trace to stderr:
// Error: Whoops, something bad happened
// at [eval]:5:15
// at Script.runInThisContext (node:vm:132:18)
// at Object.runInThisContext (node:vm:309:38)
// at node:internal/process/execution:77:19
// at [eval]-wrapper:6:22
// at evalScript (node:internal/process/execution:76:60)
// at node:internal/main/eval_string:23:3
const name = 'Will Robinson';
console.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to stderr
```
Example using the `Console` class:
```js
const out = getStreamSomehow();
const err = getStreamSomehow();
const myConsole = new console.Console(out, err);
myConsole.log('hello world');
// Prints: hello world, to out
myConsole.log('hello %s', 'world');
// Prints: hello world, to out
myConsole.error(new Error('Whoops, something bad happened'));
// Prints: [Error: Whoops, something bad happened], to err
const name = 'Will Robinson';
myConsole.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to err
```console.Console.log(message?: any, ...optionalParams: any[]): void (+1 overload)
Prints to `stdout` with newline. Multiple arguments can be passed, with the
first used as the primary message and all additional used as substitution
values similar to [`printf(3)`](http://man7.org/linux/man-pages/man3/printf.3.html)
(the arguments are all passed to [`util.format()`](https://nodejs.org/docs/latest-v22.x/api/util.html#utilformatformat-args)).
```js
const count = 5;
console.log('count: %d', count);
// Prints: count: 5, to stdout
console.log('count:', count);
// Prints: count: 5, to stdout
```
See [`util.format()`](https://nodejs.org/docs/latest-v22.x/api/util.html#utilformatformat-args) for more information.log(element: any
element));
}
This function accepts any array type through the generic constraint T
.
7. Mapped Types with Index Signatures
Square brackets in mapped types define index signatures to create dynamic property types.
type type StringMap<T> = {
[key: string]: T;
}
StringMap<function (type parameter) T in type StringMap<T>
T> = { [key: string
key: string]: function (type parameter) T in type StringMap<T>
T };
let let map: StringMap<number>
map: type StringMap<T> = {
[key: string]: T;
}
StringMap<number> = { a: number
a: 1, b: number
b: 2 };
StringMap
creates a type with string keys and values of type T
.
8. Advanced Tuple Manipulation
Square brackets enable precise tuple manipulation for extracting or omitting elements.
type type WithoutFirst<T extends any[]> = T extends [any, ...infer Rest] ? Rest : []
WithoutFirst<function (type parameter) T in type WithoutFirst<T extends any[]>
T extends any[]> = function (type parameter) T in type WithoutFirst<T extends any[]>
T extends [any, ...infer function (type parameter) Rest
Rest] ? function (type parameter) Rest
Rest : [];
type type Tail = [2, 3]
Tail = type WithoutFirst<T extends any[]> = T extends [any, ...infer Rest] ? Rest : []
WithoutFirst<[1, 2, 3]>;
WithoutFirst
removes the first element from a tuple.
Conclusion
Square brackets in TypeScript provide essential functionality, from basic array definitions to complex type manipulations. These features make TypeScript code reliable and maintainable. The growing adoption of TypeScript demonstrates the practical benefits of its robust type system.
The TypeScript Handbook provides comprehensive documentation of these features. TypeHero offers hands-on practice through interactive challenges to master TypeScript concepts, including square bracket techniques for type manipulation. These resources will strengthen your command of TypeScript and expand your programming capabilities.