Типізація функцій та змінних
Тобі дано набір JavaScript-функцій без типів. Твоє завдання -- переписати їх на TypeScript з повною типізацією: type annotations для параметрів і return, type aliases, union та literal types.
Завдання
1. Створення type aliases
Створи наступні типи:
// ID може бути рядком або числом
type ID = // ...
// Статус користувача -- один з трьох варіантів
type UserStatus = // "active" | ...
// Об'єкт користувача
type User = {
id: // ID
name: // string
email: // string
age: // number
status: // UserStatus
}
2. Типізуй функцію processArray
// Оригінал (JS):
function processArray(arr, action) {
if (action === "sum") {
return arr.reduce((acc, n) => acc + n, 0);
}
if (action === "average") {
return arr.reduce((acc, n) => acc + n, 0) / arr.length;
}
if (action === "max") {
return Math.max(...arr);
}
if (action === "min") {
return Math.min(...arr);
}
return null;
}
Вимоги:
arr-- масив чиселaction-- literal type з конкретними допустимими значеннями- Return type --
number | null
3. Типізуй функцію filterByType
// Оригінал (JS):
function filterByType(arr, typeName) {
return arr.filter(item => typeof item === typeName);
}
Вимоги:
arr-- масив(string | number | boolean)[]typeName-- literal type"string" | "number" | "boolean"- Return type --
(string | number | boolean)[]
4. Типізуй функцію calculateStats
// Оригінал (JS):
function calculateStats(numbers) {
if (numbers.length === 0) {
return { count: 0, sum: 0, average: 0, min: 0, max: 0 };
}
const sum = numbers.reduce((acc, n) => acc + n, 0);
return {
count: numbers.length,
sum,
average: sum / numbers.length,
min: Math.min(...numbers),
max: Math.max(...numbers),
};
}
Вимоги:
- Створи type alias
Statsдля об'єкта, що повертається - Параметр
numbers-- масив чисел - Return type --
Stats
5. Типізуй функцію formatUser
// Оригінал (JS):
function formatUser(user, format) {
if (format === "short") {
return user.name;
}
if (format === "medium") {
return `${user.name} (${user.email})`;
}
if (format === "full") {
return `${user.name} (${user.email}), вік: ${user.age}, статус: ${user.status}`;
}
return user.name;
}
Вимоги:
user-- типUser(створений раніше)format-- literal type- Return type --
string
6. Типізуй функцію parseConfig
// Оригінал (JS):
function parseConfig(raw) {
const config = {
host: "localhost",
port: 3000,
debug: false,
};
if (raw.host) config.host = raw.host;
if (raw.port) config.port = raw.port;
if (raw.debug !== undefined) config.debug = raw.debug;
return config;
}
Вимоги:
- Створи type alias
Configдля повного конфігу (всі поля обов'язкові) - Створи type alias
PartialConfigдля вхідного параметра (всі поля optional) - Return type --
Config
7. Типізуй функцію groupBy
// Оригінал (JS):
function groupBy(arr, key) {
return arr.reduce((groups, item) => {
const value = item[key];
if (!groups[value]) {
groups[value] = [];
}
groups[value].push(item);
return groups;
}, {});
}
Вимоги:
- Параметр
arr-- масив об'єктівUser[] - Параметр
key-- ключUser(використайkeyof) - Return type -- об'єкт з масивами
Record<string, User[]>
8. Типізуй функцію createValidator
// Оригінал (JS):
function createValidator(rules) {
return function validate(value) {
const errors = [];
for (const rule of rules) {
const error = rule(value);
if (error) errors.push(error);
}
return errors;
};
}
Вимоги:
- Створи type alias
ValidationRule-- функція(value: string) => string | null rules-- масивValidationRule[]- Return -- функція
(value: string) => string[]
Приклад використання
// 1. Types
const user: User = {
id: 1,
name: "Олексій",
email: "alex@test.com",
age: 25,
status: "active",
};
// 2. processArray
processArray([1, 2, 3, 4, 5], "sum"); // 15
processArray([10, 20, 30], "average"); // 20
// 4. calculateStats
const stats = calculateStats([10, 20, 30, 40, 50]);
// { count: 5, sum: 150, average: 30, min: 10, max: 50 }
// 5. formatUser
formatUser(user, "short"); // "Олексій"
formatUser(user, "full"); // "Олексій (alex@test.com), вік: 25, статус: active"
// 8. createValidator
const validateEmail = createValidator([
(v) => (v.length === 0 ? "Email обов'язковий" : null),
(v) => (!v.includes("@") ? "Email має містити @" : null),
]);
validateEmail(""); // ["Email обов'язковий", "Email має містити @"]
validateEmail("test"); // ["Email має містити @"]
validateEmail("test@ok.com"); // []
Бонус
- Додай generic-версію
processArray, яка працює не тільки з числами - Зроби
groupBygeneric-функцією, яка працює з будь-якими об'єктами (не тількиUser) - Додай overloading для
formatUser, де кожен формат повертає більш конкретний тип - Створи type guard функцію
isUser(value: unknown): value is Userдля валідації об'єктів
Критерії оцінки
| Критерій | Бали |
|---|---|
| Type aliases (ID, UserStatus, User, Stats, Config) | 15 |
| processArray з literal type для action | 15 |
| filterByType з union types | 10 |
| calculateStats зі Stats type alias | 15 |
| formatUser з literal type для format | 10 |
| parseConfig з PartialConfig / Config | 10 |
| groupBy з keyof | 15 |
| createValidator з function type alias | 10 |
| Бонус: generic groupBy / overloading / type guard | +20 |