Typescript: Тип object
Иногда нам нужно ограничить входной параметр функции типом «любой объект». Например, это нужно для функции, которая проверяет наличие ключей в объекте. Существует несколько способов сделать такую проверку, и не все из них работают так, как ожидается.
Посмотрим на пример:
// В качестве типа используется {}
function toString(obj: {}) {
return obj.toString();
}
toString("wow"); // Ok!
toString(123); // Ok!
toString({}); // Ok!Пустой объектный тип {} подразумевает под собой объект любой структуры и ограничивает множество всех значений, за исключением null и undefined. Пустой интерфейс работает так же как и пустой объектный тип. Это вряд ли то, что мы ожидали.
Тип Object похож на {}, но у него уже прописаны сигнатуры некоторых встроенных методов, например toString(): string. У {} таких сигнатур нет. Поэтому если мы переопределяем toString, TypeScript начинает проверять возвращаемый тип:
const foo: {} = {
toString() {
return 1; // Ok!
},
};
const bar: Object = {
toString() {
return 1; // Error!
},
};Второе определение bar не работает, потому что тип Object указывает, что метод toString() должен возвращать строку.
Если мы хотим работать с не примитивными значениями, то для этого существует еще один тип — object с маленькой буквы:
function toString(obj: object) {
return obj.toString();
}
toString("wow"); // Error!
toString(123); // Error!
toString({}); // Ok!При использовании типа object попытка получить доступ к свойствам объекта приведет к ошибке. Для такой задачи используются уже другие механизмы.
В последующих уроках мы изучим подходы, такие как использование типа Record и дженериков с keyof для работы с объектами любой структуры. А пока вы можете использовать встроенные методы JavaScript, такие как Object.entries() и Object.fromEntries(), чтобы манипулировать объектами с типом object.
Пример динамического извлечения ключей из объекта с использованием этих методов:
const extract = (obj: object, keys: Array<string>): object => {
const entries = Object.entries(obj).filter(([key]) => keys.includes(key));
return Object.fromEntries(entries);
};- Метод
Object.entries(obj)преобразует объект в массив пар [ключ, значение]. - Далее с помощью метода
filter()мы оставляем только те пары, ключи которых содержатся в массивеkeys. - Наконец,
Object.fromEntries(entries)собирает новый объект из отфильтрованных пар.
Этот подход позволяет легко работать с объектами, фильтруя ключи на основе динамических данных, даже если используется тип object, не предоставляющий доступ к свойствам напрямую.
Задание
Реализуйте функцию extract(object, keys), которая возвращает новый объект с указанными ключами. Например:
const user = {
name: "Tirion",
email: "tirion@lanister.got",
age: 35,
};
extract(user, ["name", "age"]); // { name: 'Tirion', age: 35 }Typescript: Тип object
Иногда нам нужно ограничить входной параметр функции типом «любой объект». Например, это нужно для функции, которая проверяет наличие ключей в объекте. Существует несколько способов сделать такую проверку, и не все из них работают так, как ожидается.
Посмотрим на пример:
// В качестве типа используется {}
function toString(obj: {}) {
return obj.toString();
}
toString("wow"); // Ok!
toString(123); // Ok!
toString({}); // Ok!Пустой объектный тип {} подразумевает под собой объект любой структуры и ограничивает множество всех значений, за исключением null и undefined. Пустой интерфейс работает так же как и пустой объектный тип. Это вряд ли то, что мы ожидали.
Тип Object похож на {}, но у него уже прописаны сигнатуры некоторых встроенных методов, например toString(): string. У {} таких сигнатур нет. Поэтому если мы переопределяем toString, TypeScript начинает проверять возвращаемый тип:
const foo: {} = {
toString() {
return 1; // Ok!
},
};
const bar: Object = {
toString() {
return 1; // Error!
},
};Второе определение bar не работает, потому что тип Object указывает, что метод toString() должен возвращать строку.
Если мы хотим работать с не примитивными значениями, то для этого существует еще один тип — object с маленькой буквы:
function toString(obj: object) {
return obj.toString();
}
toString("wow"); // Error!
toString(123); // Error!
toString({}); // Ok!При использовании типа object попытка получить доступ к свойствам объекта приведет к ошибке. Для такой задачи используются уже другие механизмы.
В последующих уроках мы изучим подходы, такие как использование типа Record и дженериков с keyof для работы с объектами любой структуры. А пока вы можете использовать встроенные методы JavaScript, такие как Object.entries() и Object.fromEntries(), чтобы манипулировать объектами с типом object.
Пример динамического извлечения ключей из объекта с использованием этих методов:
const extract = (obj: object, keys: Array<string>): object => {
const entries = Object.entries(obj).filter(([key]) => keys.includes(key));
return Object.fromEntries(entries);
};- Метод
Object.entries(obj)преобразует объект в массив пар [ключ, значение]. - Далее с помощью метода
filter()мы оставляем только те пары, ключи которых содержатся в массивеkeys. - Наконец,
Object.fromEntries(entries)собирает новый объект из отфильтрованных пар.
Этот подход позволяет легко работать с объектами, фильтруя ключи на основе динамических данных, даже если используется тип object, не предоставляющий доступ к свойствам напрямую.
Задание
Реализуйте функцию extract(object, keys), которая возвращает новый объект с указанными ключами. Например:
const user = {
name: "Tirion",
email: "tirion@lanister.got",
age: 35,
};
extract(user, ["name", "age"]); // { name: 'Tirion', age: 35 }Ваше упражнение проверяется по этим тестам
import { expect, test } from "vitest";
import extract from "./index";
test("extract", () => {
const obj = {
name: "John",
age: 30,
address: {
street: "Main Street",
number: 123,
},
};
expect(extract(obj, ["name", "address"])).toEqual({
name: "John",
address: obj.address,
});
expect(extract(obj, ["name", "lastName"])).toEqual({
name: "John",
});
});Решение учителя откроется через:
20:00
