string
: Used to denote a string value. For example:const name: string = 'Alice';
number
: Used to denote a numeric value. This includes both integers and floating-point values. For example:const age: number = 25;
boolean
: Used to denote a boolean value (true or false). For example:const isActive: boolean = true;
void
: Used to denote a value that has no type (e.g. a function that does not return a value). For example:function logMessage(message: string): void { console.log(message); }
null
: Used to denote a null value. For example:const value: null = null;
undefined
: Used to denote an undefined value. For example:const value: undefined = undefined;
any
: Used to denote a value that can be of any type. For example:let value: any = 'hello'; value = 123;
object
: Used to denote a value that is an object. For example:const obj: object = {};
Array
: Used to denote an array of values. The type of the values in the array can be specified using a type parameter. For example:const names: string[] = ['Alice', 'Bob', 'Charlie'];
Used to denote a fixed-length array with known element types. For example:const point: [number, number] = [0, 0]
Enum
Enum
: Used to define a set of related values. For example:
enum Color {
Red,
Green,
Blue
}
const color: Color = Color.Green;
Function
:
Used to denote a function value. The types of the arguments and the return value can be specified using type parameters. For example
type AddFunction = (x: number, y: number) => number;
const add: AddFunction = (x, y) => x + y;
console.log(add(1, 2)); // 3
In this example, we have defined a type called AddFunction
that represents a function that takes two numbers as arguments and returns a number. We have then defined a variable called add
that has the type AddFunction
, and assigned a function value to it.
We can then use the add
function as we would any other function, by calling it with the required arguments. The function type annotation ensures that the function is used correctly and that the arguments and return value have the correct types.
Class
:
class User {
constructor(public name: string, public age: number) {}
}
const user: User = new User('Alice', 25);
//Another example - Example 2
class User {
constructor(public name: string, public age: number) {}
}
type UserType = typeof User;
const UserClass: UserType = User;
const user = new UserClass('Alice', 25);
console.log(user.name); // 'Alice'
console.log(user.age); // 25
In second example, we have defined a class called User
with a name and age property. We have then defined a type called UserType
that represents the type of the User
class. We have assigned the User
class to a variable called UserClass
, which has the type UserType
.
We can then use the UserClass
variable to create new instances of the User
class, as shown in the example above. The class type annotation ensures that the class is used correctly and that the properties of the class have the correct types.
Type aliases:
Type aliases are used to create new names for existing types.
type StringOrNumber = string | number;
function concat(value1: StringOrNumber, value2: StringOrNumber): string {
return String(value1) + String(value2);
}
const result1 = concat('hello', 'world'); // 'helloworld'
const result2 = concat(1, 2); // '12'
In this example, we have defined a type alias called StringOrNumber
that represents a value that can be either a string or a number. We have then used this type alias as a type parameter for the concat
function, which concatenates two values and returns the result as a string.
We can then use the concat
function with both string and number values, as shown in the examples above. The type alias allows us to use the same function with multiple different types of values, without having to define separate functions for each type.
Interfaces
interface User {
name: string;
age: number;
}
function greet(user: User) {
console.log(`Hello, ${user.name}! You are ${user.age} years old.`);
}
const alice: User = { name: 'Alice', age: 25 };
greet(alice); // 'Hello, Alice! You are 25 years old.'
In this example, we have defined an interface called User
with a name
and age
property. We have then defined a function called greet
that takes a user object as an argument. The argument is typed as the User
interface, which means that it must have a name
and age
property with the correct types.
We have then created a variable called alice
that is typed as the User
interface, and passed it to the greet
function. The interface ensures that the alice
object has the correct structure and types, and the function is able to use the name
and age
properties as expected.
Union Types
type StringOrNumber = string | number;
function getLength(value: StringOrNumber): number {
if (typeof value === 'string') {
return value.length;
} else {
return value.toString().length;
}
}
console.log(getLength('hello')); // 5
console.log(getLength(12345)); // 5
In this example, we have defined a type called StringOrNumber
that represents a value that can be either a string or a number. We have then defined a function called getLength
that takes a value of this type as an argument and returns its length.
To handle the different types of values that the function might receive, we use a type check (typeof value === 'string'
) to determine the type of the value and perform the appropriate action.
We can then use the getLength
function with both string and number values, as shown in the examples above. The union type allows us to use the same function with multiple different types of values, without having to define separate functions for each type.
Intersection Type
interface User {
name: string;
age: number;
}
interface Admin {
canManageUsers: boolean;
}
type AdminUser = User & Admin;
const alice: AdminUser = { name: 'Alice', age: 25, canManageUsers: true };
console.log(alice.name); // 'Alice'
console.log(alice.age); // 25
console.log(alice.canManageUsers); // true
In this example, we have defined two interfaces: User
with a name
and age
property, and Admin
with a canManageUsers
property. We have then defined a type called AdminUser
that represents an object that has the properties of both the User
and Admin
interfaces.
We have then created a variable called alice
that is typed as the AdminUser
type, and assigned an object that has the required properties. The intersection type ensures that the alice
object has the correct structure and types, and we are able to access all of the properties as expected.
Type guards
function isString(value: any): value is string {
return typeof value === 'string';
}
function getLength(value: string | number): number {
if (isString(value)) {
return value.length;
} else {
return value.toString().length;
}
}
console.log(getLength('hello')); // 5
console.log(getLength(12345)); // 5
In this example, we have defined a function called isString
that takes a value of type any
and returns a boolean indicating whether the value is a string. This function is called a type guard, because it allows us to narrow the type of the value within the if
statement.
We have then defined a function called getLength
that takes a value of type string
or number
and returns its length. To handle the different types of values that the function might receive, we use the isString
type guard to determine the type of the value and perform the appropriate action.
We can then use the getLength
function with both string and number values, as shown in the examples above. The type guard ensures that the value has the correct type and allows us to use the appropriate methods and properties for that type.
Type parameters:
function createArray<T>(length: number, value: T): Array<T> {
const result: T[] = [];
for (let i = 0; i < length; i++) {
result[i] = value;
}
return result;
}
const strings = createArray<string>(3, 'hello'); // ['hello', 'hello', 'hello']
const numbers = createArray<number>(3, 123); // [123, 123, 123]
In this example, we have defined a function called createArray
that takes a length and a value, and returns an array of that value. The function uses a type parameter, T
, to represent the type of the value.
We can then call the createArray
function with different types of values, as shown in the examples above. The type parameter allows us to use the same function with multiple different types of values, without having to define separate functions for each type.
The type parameter is inferred from the type of the value argument, so in the first call to createArray
, the type parameter is inferred to be string
, and in the second call, it is inferred to be number
. This allows the function to return the correct type of array for each call.
Type assertions
let value: any = 'hello';
let strLength: number = (value as string).length;
console.log(strLength); // 5
In this example, we have defined a variable called value
with the type any
, which means that it can hold any type of value. We have then assigned a string value to the variable.
We have defined another variable called strLength
that is supposed to hold the length of the string value. To access the length property of the value
variable, we use a type assertion to tell the TypeScript compiler that the value is a string.
The type assertion is written as value as string
, and it tells the compiler to treat the value as a string, even though it has the any
type. This allows us to access the length
property of the string and assign it to the strLength
variable.
We can then use the strLength
variable as we would any other variable of type number
. The type assertion ensures that the value has the correct type and allows us to use the appropriate methods and properties for that type.