Как получить доступ к вложенным файлам с помощью Pick typescript

#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
}));