-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathTS-10.ts
More file actions
123 lines (106 loc) · 3.31 KB
/
TS-10.ts
File metadata and controls
123 lines (106 loc) · 3.31 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
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;
}
);
type CallbackBasedAsyncFunction<T> = (callback: (response: ApiResponse<T>) => void) => void;
type PromiseBasedAsyncFunction<T> = () => Promise<T>;
export function promisify<T>(fn: CallbackBasedAsyncFunction<T>): PromiseBasedAsyncFunction<T> {
return () => new Promise<T>((resolve, reject) => {
fn((response) => {
if (response.status === 'success') {
resolve(response.data);
} else {
reject(new Error(response.error));
}
});
});
}
type SourceObject<T> = {[K in keyof T]: CallbackBasedAsyncFunction<T[K]>};
type PromisifiedObject<T> = {[K in keyof T]: PromiseBasedAsyncFunction<T[K]>};
export function promisifyAll<T extends {[key: string]: any}>(obj: SourceObject<T>): PromisifiedObject<T> {
const result: Partial<PromisifiedObject<T>> = {};
for (const key of Object.keys(obj) as (keyof T)[]) {
result[key] = promisify(obj[key]);
}
return result as PromisifiedObject<T>;
}
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 = promisifyAll(oldApi);
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.`);
}
);