From 5816e155c077c347b3076668e28ef7ee33edb669 Mon Sep 17 00:00:00 2001 From: "nguyen.xuan.vinh" Date: Thu, 18 Jan 2024 17:26:42 +0700 Subject: [PATCH 1/2] ex: do typescript lesson --- vinhnx/ex1.ts | 25 +++++++++++++ vinhnx/ex2.ts | 42 ++++++++++++++++++++++ vinhnx/ex3.ts | 50 ++++++++++++++++++++++++++ vinhnx/ex4.ts | 52 +++++++++++++++++++++++++++ vinhnx/ex5.ts | 86 +++++++++++++++++++++++++++++++++++++++++++++ vinhnx/ex6.ts | 56 +++++++++++++++++++++++++++++ vinhnx/ex7.ts | 97 +++++++++++++++++++++++++++++++++++++++++++++++++++ vinhnx/ex8.ts | 86 +++++++++++++++++++++++++++++++++++++++++++++ 8 files changed, 494 insertions(+) create mode 100644 vinhnx/ex1.ts create mode 100644 vinhnx/ex2.ts create mode 100644 vinhnx/ex3.ts create mode 100644 vinhnx/ex4.ts create mode 100644 vinhnx/ex5.ts create mode 100644 vinhnx/ex6.ts create mode 100644 vinhnx/ex7.ts create mode 100644 vinhnx/ex8.ts diff --git a/vinhnx/ex1.ts b/vinhnx/ex1.ts new file mode 100644 index 0000000..d722e5a --- /dev/null +++ b/vinhnx/ex1.ts @@ -0,0 +1,25 @@ +export interface IUser { + name: string; + age: number; + occupation: string +}; + +export const users: Array = [ + { + name: 'Max Mustermann', + age: 25, + occupation: 'Chimney sweep' + }, + { + name: 'Kate Müller', + age: 23, + occupation: 'Astronaut' + } +]; + +export function logPerson(user: IUser) { + console.log(` - ${user.name}, ${user.age}`); +} + +console.log('Users:'); +users.forEach(logPerson); \ No newline at end of file diff --git a/vinhnx/ex2.ts b/vinhnx/ex2.ts new file mode 100644 index 0000000..193bd82 --- /dev/null +++ b/vinhnx/ex2.ts @@ -0,0 +1,42 @@ +interface IUser { + name: string; + age: number; + occupation: string; +} + +interface IAdmin { + name: string; + age: number; + role: string; +} + +export type TPerson = IUser | IAdmin; + +export const persons: TPerson[] = [ + { + name: 'Max Mustermann', + age: 25, + occupation: 'Chimney sweep' + }, + { + name: 'Jane Doe', + age: 32, + role: 'Administrator' + }, + { + name: 'Kate Müller', + age: 23, + occupation: 'Astronaut' + }, + { + name: 'Bruce Willis', + age: 64, + role: 'World saver' + } +]; + +export function logPerson(user: TPerson) { + console.log(` - ${user.name}, ${user.age}`); +} + +persons.forEach(logPerson); \ No newline at end of file diff --git a/vinhnx/ex3.ts b/vinhnx/ex3.ts new file mode 100644 index 0000000..63c7f36 --- /dev/null +++ b/vinhnx/ex3.ts @@ -0,0 +1,50 @@ +interface User { + name: string; + age: number; + occupation: string; +} + +interface Admin { + name: string; + age: number; + role: string; +} + +export type Person = User | Admin; + +export const persons: Person[] = [ + { + name: 'Max Mustermann', + age: 25, + occupation: 'Chimney sweep' + }, + { + name: 'Jane Doe', + age: 32, + role: 'Administrator' + }, + { + name: 'Kate Müller', + age: 23, + occupation: 'Astronaut' + }, + { + name: 'Bruce Willis', + age: 64, + role: 'World saver' + } +]; + +export function logPerson(person: Person) { + let additionalInformation: string; + + if ('role' in person) { + additionalInformation = person.role; + } else { + additionalInformation = person.occupation; + } + + console.log(` - ${person.name}, ${person.age}, ${additionalInformation}`); +} + +persons.forEach(logPerson); \ No newline at end of file diff --git a/vinhnx/ex4.ts b/vinhnx/ex4.ts new file mode 100644 index 0000000..fe8058f --- /dev/null +++ b/vinhnx/ex4.ts @@ -0,0 +1,52 @@ +interface IUser { + type: 'user'; + name: string; + age: number; + occupation: string; +} + +interface IAdmin { + type: 'admin'; + name: string; + age: number; + role: string; +} + +export type TPerson = IUser | IAdmin; + +export const persons: TPerson[] = [ + { type: 'user', name: 'Max Mustermann', age: 25, occupation: 'Chimney sweep' }, + { type: 'admin', name: 'Jane Doe', age: 32, role: 'Administrator' }, + { type: 'user', name: 'Kate Müller', age: 23, occupation: 'Astronaut' }, + { type: 'admin', name: 'Bruce Willis', age: 64, role: 'World saver' } +]; + +export function isAdmin(person: TPerson) { + return person.type === 'admin'; +} + +export function isUser(person: TPerson) { + return person.type === 'user'; +} + +export function logPerson(person: TPerson) { + let additionalInformation: string = ''; + + if (isAdmin(person)) { + additionalInformation = (person as IAdmin).role; + } + + if (isUser(person)) { + additionalInformation = (person as IUser).occupation; + } + + console.log(` - ${person.name}, ${person.age}, ${additionalInformation}`); +} + +console.log('Admins:'); +persons.filter(isAdmin).forEach(logPerson); + +console.log(); + +console.log('Users:'); +persons.filter(isUser).forEach(logPerson); \ No newline at end of file diff --git a/vinhnx/ex5.ts b/vinhnx/ex5.ts new file mode 100644 index 0000000..36379b0 --- /dev/null +++ b/vinhnx/ex5.ts @@ -0,0 +1,86 @@ +interface User { + type: 'user'; + name: string; + age: number; + occupation: string; +} + +interface Admin { + type: 'admin'; + name: string; + age: number; + role: string; +} + +export type Person = User | Admin; + +type TCriteria = { + [id in keyof User]?: User[keyof User]; +}; + +export const persons: Person[] = [ + { type: 'user', name: 'Max Mustermann', age: 25, occupation: 'Chimney sweep' }, + { + type: 'admin', + name: 'Jane Doe', + age: 32, + role: 'Administrator' + }, + { + type: 'user', + name: 'Kate Müller', + age: 23, + occupation: 'Astronaut' + }, + { + type: 'admin', + name: 'Bruce Willis', + age: 64, + role: 'World saver' + }, + { + type: 'user', + name: 'Wilson', + age: 23, + occupation: 'Ball' + }, + { + type: 'admin', + name: 'Agent Smith', + age: 23, + role: 'Administrator' + } +]; + +export const isAdmin = (person: Person): person is Admin => person.type === 'admin'; +export const isUser = (person: Person): person is User => person.type === 'user'; + +export function logPerson(person: Person) { + let additionalInformation = ''; + if (isAdmin(person)) { + additionalInformation = person.role; + } + if (isUser(person)) { + additionalInformation = person.occupation; + } + console.log(` - ${person.name}, ${person.age}, ${additionalInformation}`); +} + +export function filterUsers(persons: Person[], criteria: TCriteria): User[] { + return persons.filter(isUser).filter((user) => { + const criteriaKeys = Object.keys(criteria) as (keyof User)[]; + + return criteriaKeys.every((fieldName) => { + return user[fieldName] === criteria[fieldName]; + }); + }); +} + +console.log('Users of age 23:'); + +filterUsers( + persons, + { + age: 23 + } +).forEach(logPerson); \ No newline at end of file diff --git a/vinhnx/ex6.ts b/vinhnx/ex6.ts new file mode 100644 index 0000000..53444b3 --- /dev/null +++ b/vinhnx/ex6.ts @@ -0,0 +1,56 @@ +interface User { + type: 'user'; + name: string; + age: number; + occupation: string; +} + +interface Admin { + type: 'admin'; + name: string; + age: number; + role: string; +} + +export type Person = User | Admin; + +export const persons: Person[] = [ + { type: 'user', name: 'Max Mustermann', age: 25, occupation: 'Chimney sweep' }, + { type: 'admin', name: 'Jane Doe', age: 32, role: 'Administrator' }, + { type: 'user', name: 'Kate Müller', age: 23, occupation: 'Astronaut' }, + { type: 'admin', name: 'Bruce Willis', age: 64, role: 'World saver' }, + { type: 'user', name: 'Wilson', age: 23, occupation: 'Ball' }, + { type: 'admin', name: 'Agent Smith', age: 23, role: 'Anti-virus engineer' } +]; + +export function logPerson(person: Person) { + console.log( + ` - ${person.name}, ${person.age}, ${person.type === 'admin' ? person.role : person.occupation}` + ); +} + +const getObjectKeys = (obj: T) => Object.keys(obj as keyof T) as (keyof T)[]; + +export function filterPersons(persons: Person[], personType: User['type'], criteria: Partial>): User[]; +export function filterPersons(persons: Person[], personType: Admin['type'], criteria: Partial>): Admin[]; +export function filterPersons(persons: Person[], personType: Person['type'], criteria: Partial): Person[] { + return persons + .filter((person) => person.type === personType) + .filter((person) => { + let criteriaKeys = getObjectKeys(criteria); + return criteriaKeys.every((fieldName) => { + return person[fieldName] === criteria[fieldName]; + }); + }); +} + +export const usersOfAge23 = filterPersons(persons, 'user', { age: 23 }); +export const adminsOfAge23 = filterPersons(persons, 'admin', { age: 23 }); + +console.log('Users of age 23:'); +usersOfAge23.forEach(logPerson); + +console.log(); + +console.log('Admins of age 23:'); +adminsOfAge23.forEach(logPerson); \ No newline at end of file diff --git a/vinhnx/ex7.ts b/vinhnx/ex7.ts new file mode 100644 index 0000000..abc1439 --- /dev/null +++ b/vinhnx/ex7.ts @@ -0,0 +1,97 @@ +interface User { + type: "user"; + name: string; + age: number; + occupation: string; +} + +interface Admin { + type: "admin"; + name: string; + age: number; + role: string; +} + +function logUser(user: User) { + const pos = users.indexOf(user) + 1; + console.log(` - #${pos} User: ${user.name}, ${user.age}, ${user.occupation}`); +} + +function logAdmin(admin: Admin) { + const pos = admins.indexOf(admin) + 1; + console.log(` - #${pos} Admin: ${admin.name}, ${admin.age}, ${admin.role}`); +} + +const admins: Admin[] = [ + { + type: "admin", + name: "Will Bruces", + age: 30, + role: "Overseer", + }, + { + type: "admin", + name: "Steve", + age: 40, + role: "Steve", + }, +]; + +const users: User[] = [ + { + type: "user", + name: "Moses", + age: 70, + occupation: "Desert guide", + }, + { + type: "user", + name: "Superman", + age: 28, + occupation: "Ordinary person", + }, +]; + +export function swap( + v1: FirstType, + v2: SecondType +): [SecondType, FirstType] { + return [v2, v1]; +} + +function test1() { + console.log("test1:"); + const [secondUser, firstAdmin] = swap(admins[0], users[1]); + logUser(secondUser); + logAdmin(firstAdmin); +} + +function test2() { + console.log("test2:"); + const [secondAdmin, firstUser] = swap(users[0], admins[1]); + logAdmin(secondAdmin); + logUser(firstUser); +} + +function test3() { + console.log("test3:"); + const [secondUser, firstUser] = swap(users[0], users[1]); + logUser(secondUser); + logUser(firstUser); +} + +function test4() { + console.log("test4:"); + const [firstAdmin, secondAdmin] = swap(admins[1], admins[0]); + logAdmin(firstAdmin); + logAdmin(secondAdmin); +} + +function test5() { + console.log("test5:"); + const [stringValue, numericValue] = swap(123, "Hello World"); + console.log(` - String: ${stringValue}`); + console.log(` - Numeric: ${numericValue}`); +} + +[test1, test2, test3, test4, test5].forEach((test) => test()); diff --git a/vinhnx/ex8.ts b/vinhnx/ex8.ts new file mode 100644 index 0000000..6772317 --- /dev/null +++ b/vinhnx/ex8.ts @@ -0,0 +1,86 @@ +interface User { + type: "user"; + name: string; + age: number; + occupation: string; +} + +interface Admin { + type: "admin"; + name: string; + age: number; + role: string; +} + +// type PowerUser = Omit & Omit & { type: 'powerUser' } + +// Solution 1 +// type PowerUser = Pick> & Pick> & { type: 'powerUser' } + +// Solution 2 +type PowerUser1 = Pick> & { type: "powerUser" }; + +type User1 = PowerUser1; +type Admin1 = PowerUser1; + +type PowerUser = User1 & Admin1; + +export type Person = User | Admin | PowerUser; + +export const persons: Person[] = [ + { + type: "user", + name: "Max Mustermann", + age: 25, + occupation: "Chimney sweep", + }, + { type: "admin", name: "Jane Doe", age: 32, role: "Administrator" }, + { type: "user", name: "Kate Müller", age: 23, occupation: "Astronaut" }, + { type: "admin", name: "Bruce Willis", age: 64, role: "World saver" }, + { + type: "powerUser", + name: "Nikki Stone", + age: 45, + role: "Moderator", + occupation: "Cat groomer", + }, +]; + +function isAdmin(person: Person): person is Admin { + return person.type === "admin"; +} + +function isUser(person: Person): person is User { + return person.type === "user"; +} + +function isPowerUser(person: Person): person is PowerUser { + return person.type === "powerUser"; +} + +export function logPerson(person: Person) { + let additionalInformation: string = ""; + if (isAdmin(person)) { + additionalInformation = person.role; + } + if (isUser(person)) { + additionalInformation = person.occupation; + } + if (isPowerUser(person)) { + additionalInformation = `${person.role}, ${person.occupation}`; + } + console.log(`${person.name}, ${person.age}, ${additionalInformation}`); +} + +console.log("Admins:"); +persons.filter(isAdmin).forEach(logPerson); + +console.log(); + +console.log("Users:"); +persons.filter(isUser).forEach(logPerson); + +console.log(); + +console.log("Power users:"); +persons.filter(isPowerUser).forEach(logPerson); From 69dc36f19f803aab281e58f807b0d710130bebaf Mon Sep 17 00:00:00 2001 From: Vinh Nguyen Date: Fri, 26 Jan 2024 15:07:43 +0700 Subject: [PATCH 2/2] ex9 --- vinhnx/ex9.ts | 143 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 143 insertions(+) create mode 100644 vinhnx/ex9.ts diff --git a/vinhnx/ex9.ts b/vinhnx/ex9.ts new file mode 100644 index 0000000..ed0fc59 --- /dev/null +++ b/vinhnx/ex9.ts @@ -0,0 +1,143 @@ +interface User { + type: "user"; + name: string; + age: number; + occupation: string; +} + +interface Admin { + type: "admin"; + name: string; + age: number; + role: string; +} + +type Person = User | Admin; + +const admins: Admin[] = [ + { type: "admin", name: "Jane Doe", age: 32, role: "Administrator" }, + { type: "admin", name: "Bruce Willis", age: 64, role: "World saver" }, +]; + +const users: User[] = [ + { + type: "user", + name: "Max Mustermann", + age: 25, + occupation: "Chimney sweep", + }, + { type: "user", name: "Kate Müller", age: 23, occupation: "Astronaut" }, +]; + +export type ApiResponse = + | { + status: "success"; + data: T; + } + | { + status: "error"; + error: string; + }; + +export function requestAdmins( + callback: (response: ApiResponse) => void +) { + callback({ + status: "success", + data: admins, + }); +} + +export function requestUsers( + callback: (response: ApiResponse) => void +) { + callback({ + status: "success", + data: users, + }); +} + +export function requestCurrentServerTime( + callback: (response: ApiResponse) => void +) { + callback({ + status: "success", + data: Date.now(), + }); +} + +export function requestCoffeeMachineQueueLength( + callback: (response: ApiResponse) => void +) { + callback({ + status: "error", + error: "Numeric value has exceeded Number.MAX_SAFE_INTEGER.", + }); +} + +function logPerson(person: Person) { + console.log( + ` - ${person.name}, ${person.age}, ${ + person.type === "admin" ? person.role : person.occupation + }` + ); +} + +function startTheApp(callback: (error: Error | null) => void) { + requestAdmins((adminsResponse) => { + console.log("Admins:"); + if (adminsResponse.status === "success") { + adminsResponse.data.forEach(logPerson); + } else { + return callback(new Error(adminsResponse.error)); + } + + console.log(); + + requestUsers((usersResponse) => { + console.log("Users:"); + if (usersResponse.status === "success") { + usersResponse.data.forEach(logPerson); + } else { + return callback(new Error(usersResponse.error)); + } + + console.log(); + + requestCurrentServerTime((serverTimeResponse) => { + console.log("Server time:"); + if (serverTimeResponse.status === "success") { + console.log( + ` ${new Date(serverTimeResponse.data).toLocaleString()}` + ); + } else { + return callback(new Error(serverTimeResponse.error)); + } + + console.log(); + + requestCoffeeMachineQueueLength((coffeeMachineQueueLengthResponse) => { + console.log("Coffee machine queue length:"); + if (coffeeMachineQueueLengthResponse.status === "success") { + console.log(` ${coffeeMachineQueueLengthResponse.data}`); + } else { + return callback(new Error(coffeeMachineQueueLengthResponse.error)); + } + + callback(null); + }); + }); + }); + }); +} + +startTheApp((e: Error | null) => { + console.log(); + if (e) { + console.log( + `Error: "${e.message}", but it's fine, sometimes errors are inevitable.` + ); + } else { + console.log("Success!"); + } +});