TypeScript
TS05

TS05 Exercises

Practical Exercises

  1. Using keyof Operator

Objective: Create a type using the keyof type operator on an existing interface.

Task:

Given an interface Person, use the keyof operator to create a type that represents the keys of Person.

interface Person {
    name: string;
    age: number;
}
 
type PersonKeys = keyof Person;  // 'name' | 'age'
  1. Using typeof Operator

Objective: Create a type based on the type of an existing variable using typeof.

Task:

Declare a variable with a specific object structure and use typeof to create a type from it.

const person = {
    name: "John",
    age: 30
};
 
type PersonType = typeof person;
  1. Indexed Access Types

Objective: Use indexed access types to access a property's type.

Task:

Create an interface Person and use indexed access types to access the type of the name property.

interface Person {
    name: string;
    age: number;
}
 
type NameType = Person["name"];  // string
  1. Conditional Types

Objective: Implement a conditional type that chooses types based on conditions.

Task:

Create a conditional type CheckType that returns 'Yes' if a type extends string, otherwise 'No'.

type CheckType<T> = T extends string ? 'Yes' : 'No';
 
type result1 = CheckType<string>;  // 'Yes'
type result2 = CheckType<number>;  // 'No'
  1. Mapped Types

Objective: Create a mapped type that makes all properties of an interface optional.

Task:

Given an interface Person, create a mapped type PartialPerson.

interface Person {
    name: string;
    age: number;
}
 
type PartialPerson = {
    [P in keyof Person]?: Person[P];
};
  1. Template Literal Types

Objective: Use template literal types to construct new string types.

Task:

Create a type EventNames that represents event names like 'onClick', 'onHover', etc.

type EventNames = `on${Capitalize<string & keyof HTMLElementEventMap>}`;
  1. Utility Types

Objective: Practice using various TypeScript utility types.

Task:

Use the Partial, Readonly, Pick, Exclude, and ReturnType utility types on a sample interface or function.

interface Person {
    name: string;
    age: number;
}
 
// Partial
type PartialPerson = Partial<Person>;
 
// Readonly
type ReadonlyPerson = Readonly<Person>;
 
// Pick
type PersonName = Pick<Person, 'name'>;
 
// Exclude
type Numeric = number | string;
type JustNumber = Exclude<Numeric, string>;
 
// ReturnType
function getAge(): number {
    return 30;
}
 
type Age = ReturnType<typeof getAge>;
  1. Advanced keyof and Mapped Types

Objective: Create a mapped type that transforms all string properties of an interface to boolean properties.

Task:

Given an interface UserData, create a mapped type StringToBoolean that changes all properties of type string to boolean.

interface UserData {
    id: number;
    name: string;
    email: string;
    age: number;
}
 
type StringToBoolean<T> = {
    [P in keyof T]: T[P] extends string ? boolean : T[P];
};
 
type UserWithBooleanStrings = StringToBoolean<UserData>;
  1. Advanced Use of Conditional Types

Objective: Create a type that extracts all properties from an interface that are of a specific type.

Task:

Define a type ExtractPropertiesOfType<T, U> that extracts the keys of properties of type U from type T.

type ExtractPropertiesOfType<T, U> = {
    [K in keyof T]: T[K] extends U ? K : never;
}[keyof T];
 
interface Example {
    id: number;
    name: string;
    flag: boolean;
    createdAt: Date;
}
 
type StringKeys = ExtractPropertiesOfType<Example, string>;  // 'name'
  1. Indexed Access and Template Literal Types

Objective: Use indexed access and template literal types to create specific utility types.

Task:

Create a type EventPayloads where keys are event names (e.g., 'onClick', 'onHover') and values are the type of their respective event payloads.

type EventNames = 'onClick' | 'onHover' | 'onFocus';
type Payloads = {
    onClick: MouseEvent;
    onHover: MouseEvent;
    onFocus: FocusEvent;
};
 
type EventPayloads = {
    [K in EventNames]: Payloads[K];
};
  1. Using Exclude and Extract in a Complex Scenario

Objective: Create a utility type that excludes and extracts types based on multiple conditions.

Task:

Define a type FilterTypes<T, Include, Exclude> that includes types in T that extend Include but not Exclude.

type FilterTypes<T, Include, Exclude> = Extract<Exclude<T, Exclude>, Include>;
 
type ExampleTypes = string | number | boolean | Function;
type FilteredTypes = FilterTypes<ExampleTypes, Function | number, boolean>;
  1. Utility Types with Function Types

Objective: Manipulate function types using TypeScript utility types.

Task:

Given a function type, create a type that represents its parameters as a tuple and its return type.

type FunctionType = (name: string, age: number) => boolean;
 
type ParametersType = Parameters<FunctionType>; // [string, number]
type ReturnType = ReturnType<FunctionType>; // boolean