#typescript #mongodb #mongoose
Вопрос:
Есть этот код, который выводит ptoducts —
const products: ReadonlyArray<Pick<IProduct, 'id' | 'gender' | 'title' | 'description' | 'price' | 'imageFileName'>> = await UserDB.aggregate<
Pick<IProduct, 'id' | 'gender' | 'title' | 'description' | 'price' | 'imageFileName'>>([
**Some mongoDB action so i deleted them**
]);
Так что теперь этот products
тип-самый Pick<Iproduct, >
Когда я хочу получить доступ к полям продукта map
, я могу использовать его только таким образом —
console.log(products.map((product) => product.products.category));
И проблема в том, что я не могу использовать — product**.products**.category
из-за Pick<Iproduct, >
И именно так я могу использовать map
то, что становится неопределенным —
console.log(products.map((product) => product.category));
Что я могу с этим поделать?
Примеры данных —
{
_id: 611e2febb863ce74ac448220,
products: {
_id: 6116a9ecc3e98d500c5e523d,
category: 5,
gender: 1,
title: 'sivdosi',
description: 'oisbdvoi',
price: 2394,
imageFileName: 'http://localhost:3000/images/1628875244435-3564.png',
createdAt: 2021-08-13T17:20:44.472Z,
updatedAt: 2021-08-13T17:20:44.472Z,
__v: 0
}
}
Ответ №1:
map
Функция предназначена для массивов, поэтому я предположу, что ваш products
ключ в вашем примере-это массив, а не объект.
Во-первых, я бы посоветовал вам правильно написать определения типов для вашего ответа на продукты, если вы еще этого не сделали
interface IProduct {
_id: string,
category: number,
gender: number,
title: string,
description: string,
price: number,
imageFileName: string,
createdAt: string,
updatedAt: string,
__v: number
}
interface IResponse {
_id: string;
products: IProduct[];
}
Затем, чтобы приступить Pick
к работе с одним product
объектом, вы можете индексировать IResponse
интерфейс с помощью индексированных типов доступа. Вам нужно products
свойство в an index
, потому что это массив.
/*
Indexed Access Types
type Person = { age: number, name: string }[];
type Age = Person[number]["age"];
*/
type Products = ReadonlyArray<
Pick<
IResponse["products"][number],
"_id" | "gender" | "title" | "description" | "price" | "imageFileName"
>
>;
Если бы вы сделали что-то подобное Pick<IResponse["products"], '_id'...>
, вы бы попытались Pick
извлечь свойства из массива, что привело бы к ошибке.
И единственное, что осталось, — это сопоставить продукты с ответом на желаемую форму объекта.
// Query your products
const { products }: IResponse = {
_id: "611e2febb863ce74ac448220",
products: [
{
_id: "6116a9ecc3e98d500c5e523d",
category: 5,
gender: 1,
title: 'sivdosi',
description: 'oisbdvoi',
price: 2394,
imageFileName: 'http://localhost:3000/images/1628875244435-3564.png',
createdAt: "2021-08-13T17:20:44.472Z",
updatedAt: "2021-08-13T17:20:44.472Z",
__v: 0
}
]
}
// Get the desired object
const pickedProducts: Products = products.map(({ _id, gender, title, description, price, imageFileName }) => ({
_id,
gender,
title,
description,
price,
imageFileName
}));
Конечный результат выглядит примерно следующим образом
interface IProduct {
_id: string,
category: number,
gender: number,
title: string,
description: string,
price: number,
imageFileName: string,
createdAt: string,
updatedAt: string,
__v: number
}
interface IResponse {
_id: string;
products: IProduct[];
}
type Products = ReadonlyArray<
Pick<
IResponse["products"][number],
"_id" | "gender" | "title" | "description" | "price" | "imageFileName"
>
>;
// Query your products
const { products }: IResponse = {
_id: "611e2febb863ce74ac448220",
products: [
{
_id: "6116a9ecc3e98d500c5e523d",
category: 5,
gender: 1,
title: 'sivdosi',
description: 'oisbdvoi',
price: 2394,
imageFileName: 'http://localhost:3000/images/1628875244435-3564.png',
createdAt: "2021-08-13T17:20:44.472Z",
updatedAt: "2021-08-13T17:20:44.472Z",
__v: 0
}
]
}
// Get the desired object
const pickedProducts: Products = products.map(({ _id, gender, title, description, price, imageFileName }) => ({
_id,
gender,
title,
description,
price,
imageFileName
}));