TypeScript is a popular programming language that enhances JavaScript with static typing. By explicitly specifying types, TypeScript helps developers catch errors during development and enables better tooling support. While TypeScript offers a wide range of advanced type features, understanding the everyday types is crucial for getting started with the language.
In this article, we will explore some of the most commonly used types in TypeScript. We will discuss primitive types such as string, number, and boolean, as well as more complex types such as arrays, objects, and unions. Additionally, we will cover type inference, type assertions, and type narrowing techniques that are commonly used in TypeScript development.
Understanding these everyday types in TypeScript is essential for writing robust and bug-free code. By explicitly specifying types, developers can improve code readability, make it easier to understand and maintain, and catch potential errors early in the development process. So let’s dive into the world of TypeScript’s everyday types and harness the power of static typing!
Table of Contents
- 1 Basic Types in TypeScript
- 2 Type Inference in TypeScript
- 3 Working with Arrays in TypeScript
- 4 Working with Objects in TypeScript
- 5 Union and Intersection Types in TypeScript
- 6 Type Aliases in TypeScript
- 7 Type Guards in TypeScript
- 8 Nullable Types in TypeScript
- 9 Type Assertion in TypeScript
- 10 Enum Types in TypeScript
- 11 Generics in TypeScript
- 12 Decorators in TypeScript
- 13 FAQ:
Basic Types in TypeScript
In TypeScript, there are several basic types that you can use to define variables. These basic types include:
1. Number
The number type represents numeric values. It can be used to define whole numbers (integers) or decimal numbers (floating-point numbers). Example:
let age: number = 25;
2. String
The string type represents a sequence of characters. It can be used to store text values. Example:
let name: string = "John Doe";
3. Boolean
The boolean type represents a logical value, either true or false. Example:
let isActive: boolean = true;
4. Array
The array type represents a collection of elements of the same type. Example:
let numbers: number[] = [1, 2, 3, 4, 5];
5. Tuple
The tuple type allows you to express an array with a fixed number of elements of different types. Example:
let person: [string, number] = ["John Doe", 25];
6. Enum
The enum type allows you to define a set of named constants. Example:
enum Color {
Red,
Green,
Blue
}
let favoriteColor: Color = Color.Blue;
7. Any
The any type is a dynamic type that can hold values of any type. It is often used when the type of the value is not known at compile time. Example:
let value: any = "Hello, World!";
8. Void
The void type is used to indicate the absence of a value. It is commonly used as the return type of functions that do not return a value. Example:
function showMessage(): void {
console.log("Hello, World!");
}
9. Null and Undefined
The null and undefined types represent a variable that has no value. Example:
let data: null = null;
let result: undefined = undefined;
10. Object
The object type represents any non-primitive value, i.e., anything that is not a number, string, boolean, null, or undefined. Example:
let user: object = {
name: "John Doe",
age: 25
};
These are the basic types in TypeScript. By using these types, you can define variables with specific types and enforce type checking at compile time.
Type Inference in TypeScript
Type inference in TypeScript is the ability of the compiler to automatically determine the type of a variable or expression based on its value and context. This feature allows developers to write code without explicitly specifying types, making their code more concise and easier to read.
Variable Type Inference
When a variable is declared and initialized in the same statement, TypeScript infers its type from the value assigned to it. For example:
let num = 10; // TypeScript infers 'num' as number
let str = "hello"; // TypeScript infers 'str' as string
let bool = true; // TypeScript infers 'bool' as boolean
In the above example, the types of the variables ‘num’, ‘str’, and ‘bool’ are inferred as number, string, and boolean, respectively, based on the value assigned to them.
Function Return Type Inference
Type inference in TypeScript also applies to function return types. If a function has a return statement, the type of the returned value is automatically inferred by the compiler.
function add(a: number, b: number) {
return a + b;
}
let result = add(5, 3); // TypeScript infers 'result' as number
In the above example, the type of the ‘result’ variable is inferred as number because the add() function returns a value of type number.
Object Type Inference
TypeScript can also infer the types of object properties based on their initial values.
let person = {
name: "John",
age: 30
};
person.name; // TypeScript infers 'name' property as string
person.age; // TypeScript infers 'age' property as number
In the above code snippet, TypeScript infers the types of the ‘name’ and ‘age’ properties of the ‘person’ object as string and number, respectively.
Union Type Inference
When TypeScript encounters a variable or expression that can have multiple types, it infers a union type for that variable or expression.
let value = Math.random() > 0.5 ? "hello" : 42; // TypeScript infers 'value' as string | number
In the above example, the type of the ‘value’ variable is inferred as string | number because it can have multiple possible types: string and number.
Explicitly Specifying Types
Although TypeScript provides type inference, there are cases where developers may want to explicitly specify types to improve code clarity or handle complex scenarios.
let x: number = 5; // Explicitly specifying the type of 'x' as number
let y = "hello" as string; // Explicitly specifying the type of 'y' as string using type assertion
In the above code snippet, the types of ‘x’ and ‘y’ are explicitly specified as number and string, respectively, even though TypeScript would infer these types correctly.
Overall, type inference in TypeScript is a powerful feature that allows developers to write more concise code while preserving the benefits of static typing.
Working with Arrays in TypeScript
Arrays are an important data structure in TypeScript, allowing you to store and manipulate collections of values. TypeScript provides several features for working with arrays, including declaring array types, accessing array elements, and performing array operations.
Declaring Array Types
In TypeScript, you can declare an array type by appending square brackets (`[]`) to the type of the array elements. For example, to declare an array of numbers, you can use the `number[]` type.
const numbers: number[] = [1, 2, 3, 4, 5];
You can also use the generic `Array` type to declare an array, specifying the element type as a type argument. For example:
const strings: Array = ['hello', 'world'];
Accessing Array Elements
You can access individual elements in an array using square bracket notation with the index of the element. The index starts at 0 for the first element, and you can also use negative indices to access elements from the end of the array. For example:
const fruits: string[] = ['apple', 'banana', 'orange'];
console.log(fruits[0]); // Output: 'apple'
console.log(fruits[1]); // Output: 'banana'
console.log(fruits[-1]); // Output: 'orange'
Array Operations
TypeScript provides several built-in methods for working with arrays. Some commonly used array methods include:
forEach
: Executes a provided function once for each array element.map
: Creates a new array with the results of calling a provided function on every element in the array.filter
: Creates a new array with all elements that pass a test implemented by the provided function.reduce
: Applies a function against an accumulator and each element in the array (from left to right) to reduce it to a single value.
Here’s an example that demonstrates how to use some of these array methods:
const numbers: number[] = [1, 2, 3, 4, 5];
numbers.forEach((num) => {
console.log(num);
});
const squaredNumbers = numbers.map((num) => {
return num * num;
});
const evenNumbers = numbers.filter((num) => {
return num % 2 === 0;
});
const sum = numbers.reduce((acc, num) => {
return acc + num;
}, 0);
Conclusion
Working with arrays is a fundamental part of TypeScript development. By understanding how to declare array types, access array elements, and perform array operations, you can harness the power of arrays to manage collections of data in your TypeScript projects.
Working with Objects in TypeScript
Objects are a fundamental part of JavaScript, and TypeScript provides even stronger support for working with objects. In this section, we will explore how TypeScript allows us to define object types, access properties, and perform various operations on objects.
Defining Object Types
In TypeScript, we can define the shape of an object using the object type. We can specify the property names and their corresponding types using a syntax similar to JSON. For example:
type Person = {
name: string;
age: number;
email: string;
};
In the above code, we define a type called Person
with properties name
, age
, and email
. The types of the properties are specified using the :
syntax.
Accessing Object Properties
To access properties of an object, we can use the dot notation. For example:
const person: Person = {
name: "John Doe",
age: 30,
email: "[email protected]"
};
console.log(person.name); // "John Doe"
console.log(person.age); // 30
console.log(person.email); // "[email protected]"
In the above code, we create an object of type Person
and access its properties using the dot notation. We can access the properties and perform operations on them just like any other JavaScript object.
Object Types as Parameters and Return Types
Object types can also be used as parameter and return types in functions. For example:
function printPerson(person: Person): void {
console.log(person.name);
console.log(person.age);
console.log(person.email);
}
function createPerson(name: string, age: number, email: string): Person {
return { name, age, email };
}
In the above code, we define a function printPerson
that takes a parameter of type Person
and prints its properties. We also define a function createPerson
that creates and returns an object of type Person
based on the provided arguments.
Object Spread
One of the powerful features TypeScript provides when working with objects is object spread. With object spread, we can create new objects by copying properties from existing objects and optionally adding or overriding properties. For example:
const person: Person = {
name: "John Doe",
age: 30,
email: "[email protected]"
};
const updatedPerson = { ...person, age: 31 };
console.log(updatedPerson.name); // "John Doe"
console.log(updatedPerson.age); // 31
console.log(updatedPerson.email); // "[email protected]"
In the above code, we use object spread to create a new object called updatedPerson
based on the person
object. We override the age
property to update the person’s age. The remaining properties are copied from the original object.
Conclusion
Working with objects is a crucial part of any JavaScript project, and TypeScript makes it easier and safer by providing strong typing and additional features like object spread. By defining object types, accessing properties, and performing operations on objects, we can build more robust and maintainable code.
Union and Intersection Types in TypeScript
In TypeScript, you can create complex types by combining existing types using union and intersection types.
Union Types
A union type allows a value to be of two or more different types. When defining a union type, you separate the type options using the pipe “|” operator.
For example:
type Status = "success" | "error" | "in progress";
In the above example, the type “Status” can only have three possible values: “success”, “error”, or “in progress”.
Union types are useful when a value can have multiple possible types, such as when handling different response types from an API.
Intersection Types
An intersection type combines multiple types to create a new type that includes all the properties and methods from each of the individual types.
For example:
interface Shape {
color: string;
}
interface Size {
size: number;
}
type ColoredShape = Shape & Size;
In this example, the “ColoredShape” type is an intersection of the “Shape” and “Size” interfaces. It will have both the “color” property from the “Shape” interface and the “size” property from the “Size” interface.
Intersection types are useful when you want to create a type that has all the properties and methods of multiple types.
Type Guards and Type Assertions
When working with union types, you may need to narrow down the possible types to perform different operations based on the actual type.
One way to do this is by using type guards. Type guards are functions that help you narrow down the possible types within a union type based on some runtime check.
Another way is by using type assertions. Type assertions allow you to assert that a value is of a specific type. This can be useful when you know more about the value’s type than TypeScript does.
Conclusion
Union and intersection types are powerful features in TypeScript that allow you to create complex types by combining existing types. Union types are useful when a value can have multiple possible types, and intersection types are useful when you want to create a type that has all the properties and methods of multiple types.
Type Aliases in TypeScript
Type aliases in TypeScript allow you to create custom names for new types. They provide a way to define complex types that can be reused throughout your codebase.
Creating a Type Alias
To create a type alias, you use the `type` keyword followed by the name of the alias and an equal sign. After the equal sign, you define the type that the alias represents.
Here’s an example:
type Person = {
name: string;
age: number;
address: string;
};
In this example, we defined a type alias called `Person` that represents an object with properties `name`, `age`, and `address`, all with specific types.
Using Type Aliases
Once you have defined a type alias, you can use it just like any other type in TypeScript. For example, you can use it to annotate function parameters or variables:
function greet(person: Person) {
console.log(`Hello, ${person.name}`);
}
const john: Person = {
name: 'John Doe',
age: 25,
address: '123 Main St',
};
greet(john);
In this example, we defined a function `greet` that takes a `Person` object as its parameter. We also created a variable `john` that is of type `Person`, and called the `greet` function passing `john` as an argument.
Type Aliases with Union Types
Type aliases can also be used with union types to create more flexible types. Here’s an example:
type Status = 'active' | 'inactive' | 'pending';
type User = {
name: string;
status: Status;
};
In this example, we defined a type alias called `Status` that represents a union of three string literals: `’active’`, `’inactive’`, and `’pending’`. We then used this type alias to define a `User` type with properties `name` and `status`.
Advantages of Type Aliases
Type aliases can make your code more readable and maintainable by providing meaningful names for complex types. They also allow you to define reusable types, reducing duplication and improving consistency throughout your codebase.
Furthermore, type aliases can be used in conjunction with intersection types, type guards, and other advanced TypeScript features to create powerful and expressive types.
Overall, type aliases are a useful tool in TypeScript that can help you write more robust and expressive code.
Type Guards in TypeScript
TypeScript provides a feature called type guards that allows us to narrow down the type of a variable based on a specific condition. Type guards are especially useful when working with union types, where a single variable can have multiple possible types.
Using type predicates
One way to implement a type guard is by using a type predicate. A type predicate is a function that takes in an argument and returns a boolean value indicating the type of the argument. Here’s an example:
“`typescript
function isNumber(value: unknown): value is number {
return typeof value === ‘number’;
}
“`
In this example, the `isNumber` function is a type predicate that checks if the given value is of type `number`. By using the `value is number` syntax, we can narrow down the type of a variable inside the function’s body.
Using typeof and instanceof operators
TypeScript also provides other ways to create type guards. The `typeof` operator can be used to check the type of a primitive value, such as a number or a string. Here’s an example:
“`typescript
function logLength(value: string | number) {
if (typeof value === ‘string’) {
console.log(value.length);
} else if (typeof value === ‘number’) {
console.log(value.toString().length);
}
}
“`
In this example, the `logLength` function accepts a parameter of type `string` or `number`. Inside the function, we use the `typeof` operator to check the type of the `value` variable and perform different operations accordingly.
The `instanceof` operator can be used to check if an object is an instance of a specific class. Here’s an example:
“`typescript
class Animal {
name: string;
constructor(name: string) {
this.name = name;
}
}
class Dog extends Animal {
breed: string;
constructor(name: string, breed: string) {
super(name);
this.breed = breed;
}
}
function isDog(animal: Animal): animal is Dog {
return animal instanceof Dog;
}
“`
In this example, the `isDog` function checks if the given `animal` object is an instance of the `Dog` class. By using the `animal is Dog` syntax, we can narrow down the type of the `animal` variable inside the function’s body.
Using user-defined type guards
In addition to the built-in type guards, TypeScript allows us to define our own type guards. A user-defined type guard is a function that returns a type predicate. Here’s an example:
“`typescript
function isEvenNumber(value: number): value is number {
return value % 2 === 0;
}
function getEvenNumbers(numbers: number[]): number[] {
return numbers.filter(isEvenNumber);
}
“`
In this example, the `isEvenNumber` function is a user-defined type guard that checks if the given `value` is an even number. By using the `value is number` syntax, we can narrow down the type of the `value` variable inside the function’s body. The `getEvenNumbers` function uses the `isEvenNumber` type guard to filter out the even numbers from the `numbers` array.
Type guards are a powerful feature of TypeScript that help us write more type-safe code. By narrowing down the type of a variable, we can eliminate potential runtime errors and make our code more robust.
Nullable Types in TypeScript
One of the key features of TypeScript is its ability to work with nullable types. Nullable types allow variables to hold a value of either the specified type or null. This is especially useful when dealing with optional or potentially missing data.
Using the question mark (?)
In TypeScript, you can define a nullable type by appending a question mark (?) to the end of the type. For example, string | null
represents a nullable string type.
Here’s an example:
let username: string | null = "John";
username = null;
In the above code, the variable username
is initially assigned a string value, but it can be later set to null.
Working with Nullable Types
When working with nullable types, you need to handle the possibility of null values. You can do this by using conditionals or type guards to check if a value is null before performing any operations on it.
Here’s an example:
let username: string | null = "John";
if (username !== null) {
// Perform some operations on the username
console.log(username.toUpperCase());
} else {
console.log("Username is null");
}
In the above code, we first check if the username
variable is null. If it isn’t, we can safely perform operations on it. Otherwise, we handle the case where the username
is null.
Nullable Types in Functions
Nullable types can also be used in function parameters and return types. For example, you can define a function that accepts a string | null
parameter:
function greetUser(name: string | null) {
if (name !== null) {
console.log(`Hello, ${name}!`);
} else {
console.log("Hello, user!");
}
}
greetUser("John");
greetUser(null);
In the above code, the greetUser
function accepts a name
parameter of type string | null
. It checks if the name
is null before logging the appropriate greeting.
Conclusion
Nullable types in TypeScript allow for more flexibility when working with optional or potentially missing values. By using nullable types, you can handle null values gracefully and avoid runtime errors.
Type Assertion in TypeScript
Type Assertion is a way to tell the TypeScript compiler about the type of a value. It allows us to explicitly specify the type of a variable, even when the compiler cannot infer it. Type Assertion is also known as “Type Casting”. It is a way to tell the compiler “Trust me, I know what I’m doing.”
There are two syntaxes for Type Assertion in TypeScript:
Syntax 1: Angle Bracket
The angle bracket syntax is the older syntax for Type Assertion in TypeScript. It looks like this:
let someValue: any = "hello world";
let strLength: number = (
In the above example, we have a variable “someValue” of type “any”, which means it can have any value. We want to calculate the length of the string, so we use the type assertion syntax to tell the compiler that “someValue” is of type “string”. We then access the “length” property of the string using the type assertion.
Syntax 2: as keyword
The as keyword syntax is the newer and recommended syntax for Type Assertion in TypeScript. It looks like this:
let someValue: any = "hello world";
let strLength: number = (someValue as string).length;
In this syntax, we use the as keyword followed by the desired type in parentheses. This tells the compiler that we are asserting the type of the variable.
Both syntaxes achieve the same result, so you can choose the one you are comfortable with. However, the as keyword syntax is more consistent with JSX syntax and is recommended by the TypeScript team.
It is important to note that Type Assertion does not have any runtime impact. It is purely a way to provide hints to the TypeScript compiler so that it can perform type checking during development. The compiled JavaScript code remains the same.
It is also worth mentioning that Type Assertion should be used with caution. It essentially tells the compiler to trust the developer’s assertion about the type. If the assertion is incorrect, it can lead to runtime errors. Therefore, it is recommended to use Type Assertion only when necessary and when you are confident about the type you are asserting.
In summary, Type Assertion is a way to tell the TypeScript compiler about the type of a value. It allows us to explicitly specify the type of a variable when the compiler cannot infer it. There are two syntaxes for Type Assertion: the angle bracket syntax and the as keyword syntax. Type Assertion should be used with caution, as it can lead to runtime errors if the assertion is incorrect.
Enum Types in TypeScript
Enumerated types, or enums, allow developers to define a set of named values. Enums provide a way to create a collection of related values and make the code more readable and maintainable.
In TypeScript, enums are a type that specifies a set of named constants as a distinct type, similar to an integer or string type. Enums in TypeScript can be used to define a set of possible values for a variable, making it easier to work with and enforce constraints.
Defining an Enum Type
To define an enum type in TypeScript, you can use the enum
keyword followed by the name of the enum and a set of values enclosed in curly braces:
enum Direction {
Up,
Down,
Left,
Right
}
In the example above, we define an enum called Direction
with four possible values: Up
, Down
, Left
, and Right
. By default, each value in the enum is assigned a numeric value starting from 0.
Working with Enum Types
Once an enum type is defined, you can use it to declare variables and assign one of its values:
let dir: Direction = Direction.Up;
let opposite: Direction = Direction.Down;
In the example above, we declare two variables: dir
and opposite
. We assign the Direction.Up
value to dir
and the Direction.Down
value to opposite
.
You can also use an enum type as the type annotation for function parameters and return values:
function move(direction: Direction): void {
// code here
}
function getOpposite(direction: Direction): Direction {
// code here
}
In the functions above, the direction
parameter is of type Direction
and the return type is also Direction
.
Enum Values and Constants
Enums in TypeScript are useful for defining a set of values that represent options or choices. The values in an enum can be used as constants throughout your code, which can improve code readability and eliminate magic numbers.
You can access the numeric value associated with an enum value using dot notation:
console.log(Direction.Up); // 0
console.log(Direction.Down); // 1
console.log(Direction.Left); // 2
console.log(Direction.Right); // 3
If you want to assign custom values to enum members, you can do so by specifying the value explicitly:
enum Direction {
Up = 1,
Down = 2,
Left = 4,
Right = 8
}
In the example above, we assign custom values to the enum members. Now, Direction.Up
is 1, Direction.Down
is 2, Direction.Left
is 4, and Direction.Right
is 8.
Iterating Over Enum Values
You can iterate over the values of an enum using a loop:
for (const direction in Direction) {
if (typeof Direction[direction] === 'number') {
console.log(direction);
}
}
In the example above, we iterate over the keys of the Direction
enum and log each key to the console. By checking the type of each value, we ensure that only the enum members are logged, excluding any other properties or methods.
Conclusion
Enums in TypeScript provide a way to define a set of named values and use them as a distinct type. By using enum types, you can enforce constraints and make your code more readable and maintainable. Enum values can also be used as constants throughout your code, improving code readability and eliminating magic numbers.
Generics in TypeScript
Generics in TypeScript is a powerful feature that allows you to write reusable code by creating templates for types. It enables you to specify placeholders for the types of function arguments, return values, and variables, providing flexibility and type safety.
Why use generics?
Generics help you write reusable code that can work with a variety of data types. They enable you to create functions, classes, and interfaces that are parameterized with type variables. This allows you to write code that can handle different types without sacrificing type safety.
By using generics, you can create more flexible and generic functions and classes. For example, instead of creating separate functions for sorting different types of arrays, you can write a generic function that can handle any array type.
How to use generics
To use generics in TypeScript, you need to define type variables using angle brackets (<>
) after the function or class name. You can then use these type variables throughout the function or class to represent unknown types.
For example, here’s a simple generic function that swaps the values of two variables:
function swap<T>(a: T, b: T): void {
let temp: T = a;
a = b;
b = temp;
}
You can use this function with any type, such as numbers, strings, or even custom types:
let x: number = 5;
let y: number = 10;
swap(x, y);
let name1: string = "Alice";
let name2: string = "Bob";
swap(name1, name2);
Constraints on generics
In some cases, you may want to apply constraints on the types that can be used with generics. TypeScript allows you to do this by using the extends
keyword to specify a constraint.
For example, let’s say you want to create a generic function that can only accept types that have a length
property. You can apply this constraint by using the extends
keyword:
function printLength<T extends { length: number }>(arg: T): void {
console.log(arg.length);
}
This function can now only be called with types that have a length
property, ensuring type safety.
Conclusion
Generics in TypeScript provide a way to write reusable code that can work with different data types while maintaining type safety. They allow you to create flexible and generic functions, classes, and interfaces, making your code more efficient and easier to maintain.
By understanding and utilizing generics, you can write more expressive and robust TypeScript code.
Decorators in TypeScript
In TypeScript, decorators provide a way to add functionality to classes, properties, methods, or parameters at design time. They allow you to modify or enhance the behavior of existing code without modifying its source code.
Class Decorators
Class decorators are applied to classes and are used to modify the behavior of the class itself. They are prefixed with the “@” symbol and placed immediately before the class declaration.
For example, let’s say we have a class decorator that logs a message every time an instance of a class is created:
“`typescript
function logClass(target: Function) {
console.log(`Class “${target.name}” is instantiated.`);
}
@logClass
class MyClass {
constructor() {
console.log(‘Creating an instance of MyClass’);
}
}
const myInstance = new MyClass(); // Output:
// Class “MyClass” is instantiated.
// Creating an instance of MyClass
“`
Property Decorators
Property decorators are used to modify class properties. They are declared just before the property declaration.
For example, let’s say we have a property decorator that logs a message every time a property is set:
“`typescript
function logProperty(target: Object, key: string) {
let value = this[key];
const getter = () => {
return value;
};
const setter = (newValue: string) => {
console.log(`Setting property ${key} to ${newValue}`);
value = newValue;
};
Object.defineProperty(target, key, {
get: getter,
set: setter,
});
}
class MyClass {
@logProperty
myProperty: string = ‘initial value’;
}
const myInstance = new MyClass();
myInstance.myProperty = ‘new value’; // Output: Setting property myProperty to new value
“`
Method Decorators
Method decorators are used to modify class methods. They are declared just before the method declaration.
For example, let’s say we have a method decorator that logs the arguments and return value of a method:
“`typescript
function logMethod(target: any, key: string, descriptor: PropertyDescriptor) {
const originalMethod = descriptor.value;
descriptor.value = function (…args: any[]) {
console.log(`Calling method ${key} with arguments: ${args}`);
const result = originalMethod.apply(this, args);
console.log(`Method ${key} returned: ${result}`);
return result;
};
return descriptor;
}
class MyClass {
@logMethod
myMethod(arg1: string, arg2: number): string {
return `Received arguments: ${arg1}, ${arg2}`;
}
}
const myInstance = new MyClass();
myInstance.myMethod(‘hello’, 42); // Output:
// Calling method myMethod with arguments: hello, 42
// Method myMethod returned: Received arguments: hello, 42
“`
Parameter Decorators
Parameter decorators are used to modify the behavior of function or method parameters. They are declared just before the parameter declaration.
For example, let’s say we have a parameter decorator that logs the value of a parameter:
“`typescript
function logParameter(target: any, key: string, index: number) {
const originalMethod = target[key];
target[key] = function (…args: any[]) {
console.log(`Parameter ${index} value: ${args[index]}`);
return originalMethod.apply(this, args);
};
}
class MyClass {
myMethod(@logParameter arg1: string, arg2: number): string {
return `Received arguments: ${arg1}, ${arg2}`;
}
}
const myInstance = new MyClass();
myInstance.myMethod(‘hello’, 42); // Output: Parameter 0 value: hello
“`
These are just a few examples of what you can achieve with decorators in TypeScript. Decorators provide a powerful way to augment the behavior of your code and are an important tool in the TypeScript ecosystem.
FAQ:
What is TypeScript?
TypeScript is a statically typed superset of JavaScript that compiles to plain JavaScript.
What are the advantages of using TypeScript?
There are several advantages of using TypeScript. The main advantage is its static typing, which helps catch errors at compile-time and enhances code quality. TypeScript also offers advanced features like interfaces, classes, and modules that make large-scale JavaScript projects more maintainable. Another advantage is its ability to provide type inference and code completion in IDEs.
How do you declare a variable with a specific type in TypeScript?
In TypeScript, you can declare a variable with a specific type using the colon syntax. For example: “let age: number = 25;”. This declares a variable “age” of type “number” with an initial value of 25.
What is the any type in TypeScript?
The “any” type in TypeScript represents a dynamic type. It allows you to assign any value to a variable, regardless of its type. It can be useful when dealing with legacy JavaScript code or when you don’t know the exact type of a value. However, overusing the “any” type can undermine the benefits of TypeScript’s static typing and might result in less predictable code.
What are union types in TypeScript?
Union types allow a variable to have multiple possible types. They are denoted using the pipe symbol (|) between the types. For example: “let result: number | string;”. This declares a variable “result” that can hold either a number or a string. You can use type guards or type assertions to narrow down the actual type of the variable at runtime.