Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
108 changes: 108 additions & 0 deletions ex1_hoanglx/ex1.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
/*

Welcome to:

................................................................
. .
. #################### #################### E .
. #################### #################### X .
. #### #### E .
. #### #### R .
. #### #################### C .
. #### #### I .
. #### #### S .
. #### #################### E .
. #### #################### S .
. .
................................................................

The goal: Let everyone play with many different TypeScript features
and get an overview of TypeScript capabilities and principles.

Things to cover:

1. Basic typing.
2. Refining types.
3. Union types.
4. Merged types.
5. Generics.
6. Type declarations.
7. Module augmentation.
8. Advanced type mapping.

Rules and principles:

1. Avoid using "any" type at all costs.
2. Difficulty quickly grows one exercise after another.
3. Feel free to send pull requests if you've come up
with improvements!
4. Provide feedback to the creator of these exercises.
5. Enjoy.

Brief UI guide:

+--------------------------------------------------------------+
| TypeScript exercises |
+--------------------------------------------------------------+
| Exercises 1·2·3·4... << Navigate through exercises >> |
+---------------+----------------------------------------------+
| Files | file.ts << Filename and status >> |
+---------------+----------------------------------------------+
| file.ts | 1 import {x} from 'y'; |
| dir | 2 |
| sub.ts | 3 |
| | |
| << Current | << Currently selected file code editor >> |
| exercise file | |
| structure >> +----------------------------------------------+
| | |
| | << Errors to fix in order to proceed >> |
| | |
+---------------+----------------------------------------------+

Intro:

We are starting a small community of users. For performance
reasons, we have decided to store all users right in the code.
This way we can provide our developers with more
user-interaction opportunities. With user-related data, at least.
All the GDPR-related issues will be solved some other day.
This would be the basis for our future experiments during
these exercises.

Exercise:

Given the data, define the interface "User" and use it accordingly.

*/


interface User {
name: string;
age: number;
occupation: string;
};

export const users: User[] = [
{
name: 'Max Mustermann',
age: 25,
occupation: 'Chimney sweep'
},
{
name: 'Kate Müller',
age: 23,
occupation: 'Astronaut'
}
];

export function logPerson(user: User) {
console.log(` - ${user.name}, ${user.age}`);
}

console.log('Users:');
users.forEach(logPerson);


// In case you are stuck:
// https://www.typescriptlang.org/docs/handbook/2/objects.html
155 changes: 155 additions & 0 deletions ex1_hoanglx/ex10.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
/*

Intro:

We have asynchronous functions now, advanced technology.
This makes us a tech startup officially now.
But one of the consultants spoiled our dreams about
inevitable future IT leadership.
He said that callback-based asynchronicity is not
popular anymore and everyone should use Promises.
He promised that if we switch to Promises, this would
bring promising results.

Exercise:

We don't want to reimplement all the data-requesting
functions. Let's decorate the old callback-based
functions with the new Promise-compatible result.
The final function should return a Promise which
would resolve with the final data directly
(i.e. users or admins) or would reject with an error
(or type Error).

The function should be named promisify.

Higher difficulty bonus exercise:

Create a function promisifyAll which accepts an object
with functions and returns a new object where each of
the function is promisified.

Rewrite api creation accordingly:

const api = promisifyAll(oldApi);

*/

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<T> = (
{
status: 'success';
data: T;
} |
{
status: 'error';
error: string;
}
);

export function promisify<T>(callbackFunction: (callback: (response: ApiResponse<T>) => void) => void): () => Promise<T> {
return () => {
return new Promise<T>((resolve, reject) => {
callbackFunction((response) => {
if (response.status === 'success') {
resolve(response.data);
} else {
reject(new Error(response.error));
}
});
});
};
}
const oldApi = {
requestAdmins(callback: (response: ApiResponse<Admin[]>) => void) {
callback({
status: 'success',
data: admins
});
},
requestUsers(callback: (response: ApiResponse<User[]>) => void) {
callback({
status: 'success',
data: users
});
},
requestCurrentServerTime(callback: (response: ApiResponse<number>) => void) {
callback({
status: 'success',
data: Date.now()
});
},
requestCoffeeMachineQueueLength(callback: (response: ApiResponse<number>) => void) {
callback({
status: 'error',
error: 'Numeric value has exceeded Number.MAX_SAFE_INTEGER.'
});
}
};

export const api = {
requestAdmins: promisify(oldApi.requestAdmins),
requestUsers: promisify(oldApi.requestUsers),
requestCurrentServerTime: promisify(oldApi.requestCurrentServerTime),
requestCoffeeMachineQueueLength: promisify(oldApi.requestCoffeeMachineQueueLength)
};

function logPerson(person: Person) {
console.log(
` - ${person.name}, ${person.age}, ${person.type === 'admin' ? person.role : person.occupation}`
);
}

async function startTheApp() {
console.log('Admins:');
(await api.requestAdmins()).forEach(logPerson);
console.log();

console.log('Users:');
(await api.requestUsers()).forEach(logPerson);
console.log();

console.log('Server time:');
console.log(` ${new Date(await api.requestCurrentServerTime()).toLocaleString()}`);
console.log();

console.log('Coffee machine queue length:');
console.log(` ${await api.requestCoffeeMachineQueueLength()}`);
}

startTheApp().then(
() => {
console.log('Success!');
},
(e: Error) => {
console.log(`Error: "${e.message}", but it's fine, sometimes errors are inevitable.`);
}
);

// In case you are stuck:
// https://www.typescriptlang.org/docs/handbook/2/generics.html
65 changes: 65 additions & 0 deletions ex1_hoanglx/ex2.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/*

Intro:

All 2 users liked the idea of the community. We should go
forward and introduce some order. We are in Germany after all.
Let's add a couple of admins.

Initially, we only had users in the in-memory database. After
introducing Admins, we need to fix the types so that
everything works well together.

Exercise:

Type "Person" is missing, please define it and use
it in persons array and logPerson function in order to fix
all the TS errors.

*/

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[] /* <- 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(user: Person) {
console.log(` - ${user.name}, ${user.age}`);
}

persons.forEach(logPerson);

// In case you are stuck:
// https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#union-types
Loading