Привет! Хотя регулярность постов и изменилась, неделя по-прежнему начинается с разбора задач с собеседований)
У нас есть пример типизированого массива:
И дана функция поиска по массиву, которую нужно типизировать:
Пример использования этой функции с массивом:
Задача:
Типизировать функцию
Решение:
1.
-
-
2. Параметры функции:
-
-
-
Вот и все) Мы типизировали функцию с помощью дженериков и сделали её универсальной для любых подобных массивов. Теперь мы можем гарантировать, что функция будет принимать только валидные аргументы.
В этом примере я не указал явно тип возвращаемого значения, так как TypeScript подтянет его автоматически. Но если функция будет меняться, лучше явно прописывать возвращаемый тип, чтобы избежать случайных ошибок в будущем.
#JavaScript #interview #typescript
У нас есть пример типизированого массива:
interface Student {
name: string;
age: number;
hasScar: boolean;
}
const students: Student[] = [
{ name: "Harry", age: 17, hasScar: true },
{ name: "Ron", age: 17, hasScar: false },
{ name: "Hermione", age: 16, hasScar: false },
];
И дана функция поиска по массиву, которую нужно типизировать:
function getBy(arr, prop, value) {
return arr.find(item => item[prop] === value) || null;
}
Пример использования этой функции с массивом:
const result = getBy(students, "name", "Hermione");
console.log(result);
Задача:
Типизировать функцию
getBy. Решение:
function getBy<T, K extends keyof T>(arr: T[], prop: K, value: T[K]) {
return arr.find(item => item[prop] === value) || null;
}
1.
<T, K extends keyof T> — дженерик:-
T — это универсальный тип, который представляет тип объекта внутри массива arr.-
K extends keyof T — означает, что K — это ключ объекта T. Тип keyof T — это объединение всех ключей объекта T. 2. Параметры функции:
-
arr: T[] — массив объектов типа T.-
prop: K — ключ, по которому будем искать совпадение.-
value: T[K] — значение, с которым будем сравнивать. Тип значения автоматически подтягивается из типа свойства prop. Вот и все) Мы типизировали функцию с помощью дженериков и сделали её универсальной для любых подобных массивов. Теперь мы можем гарантировать, что функция будет принимать только валидные аргументы.
В этом примере я не указал явно тип возвращаемого значения, так как TypeScript подтянет его автоматически. Но если функция будет меняться, лучше явно прописывать возвращаемый тип, чтобы избежать случайных ошибок в будущем.
#JavaScript #interview #typescript
👍8🔥4🤯4
Сегодня у нас очередная задача с собеседования, связанная с рекурсией)
Задача:
Нужно распарсить вложенный объект, чтобы получить значение самого глубокого уровня.
Пример вызова функции:
Решение:
1.
2. Берём первое значение —
3. Если это значение — не объект, возвращаем его.
4. Если это объект, вызываем
Для кого-то эта задача может показаться совсем простой, но на практике некоторые мидлы задумываются над ней.
#interview #JavaScript
Задача:
Нужно распарсить вложенный объект, чтобы получить значение самого глубокого уровня.
Пример вызова функции:
const obj = { red: { fast: { fancy: { car: "lamba" } } } };
console.log(objParse(obj)); // "lamba"
Решение:
function objParse(obj) {
const [value] = Object.values(obj); // 1, 2
if (typeof value !== "object") { // 3
return value;
}
return objParse(value); // 4
}
1.
Object.values(obj) возвращает массив всех значений объекта. 2. Берём первое значение —
value.3. Если это значение — не объект, возвращаем его.
4. Если это объект, вызываем
objParse рекурсивно.Для кого-то эта задача может показаться совсем простой, но на практике некоторые мидлы задумываются над ней.
#interview #JavaScript
🔥9👍4
Недавно мы разбирали(тык) работу с ошибками в JS.
Сегодня рассмотрим создание кастомных ошибок. Они позволяют точнее описывать, что именно пошло не так, и обрабатывать ошибки более точечно.
Вместо обычного
Что происходит?
1. Мы наследуемся от встроенного
2. Функция
3. В блоке
4. В блоке
Зачем это нужно?
1. Проще различать типы ошибок
2. Можно точечно обрабатывать нужные ошибки с помощью
3. Можно сделать более детальные ошибки.
#JavaScript #BestPractices
Сегодня рассмотрим создание кастомных ошибок. Они позволяют точнее описывать, что именно пошло не так, и обрабатывать ошибки более точечно.
Вместо обычного
Error можно создать свой класс, унаследованный от него:
class ValidationError extends Error { // 1
constructor(message) {
super(message);
this.name = "ValidationError";
}
}
function validateUser(user) { // 2
if (!user.name) {
throw new ValidationError("Поле 'name' обязательно");
}
}
try {
validateUser({}); // 3
} catch (error) {
if (error instanceof ValidationError) { // 4
console.error("Ошибка валидации:", error.message);
} else {
throw error;
}
}
Что происходит?
1. Мы наследуемся от встроенного
Error, чтобы определить новый тип ошибки — ValidationError.2. Функция
validateUser проверяет, есть ли у объекта поле name. Если его нет — выбрасывает кастомную ошибку ValidationError с понятным сообщением.3. В блоке
try вызываем validateUser, передавая объект без name.4. В блоке
catch ловим ошибку и проверяем, является ли она экземпляром ValidationError с помощью instanceof.Зачем это нужно?
1. Проще различать типы ошибок
2. Можно точечно обрабатывать нужные ошибки с помощью
instanceof.3. Можно сделать более детальные ошибки.
#JavaScript #BestPractices
👍11🔥3👏1