Машинописный текст перемещает объект из одного массива в другой

#typescript

Вопрос:

Мне нужно переместить элементы из одного массива в другой в машинописном виде. Но проблема отличается от обычной. Мне нужно перенести объект из массива, находящегося в другом объекте, в другой массив, находящийся в другом объекте 🙂

Вот мой файл transfer.ts

 type List = unknown;
export default function move(list: List, source: string, destination: string): List {
}
 

Вот файл спецификации

 import move from './transfer';

describe('move', () => {
it('moves given file to another folder', () => {
const list = [
  {
    id: '1',
    name: 'Folder 1',
    files: [
      { id: '2', name: 'File 1' },
      { id: '3', name: 'File 2' },
      { id: '4', name: 'File 3' },
      { id: '5', name: 'File 4' },
    ],
  },
  {
    id: '6',
    name: 'Folder 2',
    files: [{ id: '7', name: 'File 5' }],
  },
 ];

 const result = [
  {
    id: '1',
    name: 'Folder 1',
    files: [
      { id: '2', name: 'File 1' },
      { id: '3', name: 'File 2' },
      { id: '5', name: 'File 4' },
    ],
  },
  {
    id: '6',
    name: 'Folder 2',
    files: [
      { id: '7', name: 'File 5' },
      { id: '4', name: 'File 3' },
    ],
   },
 ];

 expect(move(list, '4', '6')).toStrictEqual(result);
 });

 it('throws error if given source is not a file', () => {
  const list = [
  {
    id: '1',
    name: 'Folder 1',
    files: [{ id: '2', name: 'File 1' }],
  },
  { id: '3', name: 'Folder 2', files: [] },
  ];

 expect(() => move(list, '3', '1')).toThrow('You cannot move a folder');
 });

 it('throws error if given destination is not a folder', () => {
 const list = [
  {
    id: '1',
    name: 'Folder 1',
    files: [{ id: '2', name: 'File 1' }],
  },
  { id: '3', name: 'Folder 2', files: [{ id: '4', name: 'File 2' }] },
];

  expect(() => move(list, '2', '4')).toThrow('You cannot specify a file as the 
  destination');
 });
 });
 

Мне нужно создать «Список типов» и переместить элементы, как показано в файле спецификации.

Как я могу это сделать?

Ответ №1:

Я разделил функции как можно больше, чтобы улучшить читаемость кода, если что-то не совсем понятно, не стесняйтесь спрашивать!

 
// type definitions
type CustomFile = { id: string; name: string };

type Folder = {
    id: string;
    name: string;
    files: CustomFile[];
};

// --------

const list: Folder[] = [
    {
        id: "1",
        name: "Folder 1",
        files: [
            { id: "2", name: "File 1" },
            { id: "3", name: "File 2" },
            { id: "4", name: "File 3" },
            { id: "5", name: "File 4" }
        ]
    },
    {
        id: "6",
        name: "Folder 2",
        files: [{ id: "7", name: "File 5" }]
    }
];



// this function will recognize why file cannot be found inside the list
function recognizeFileSearchError(list: Folder[], fileId: string, destinationId: string): never {

    // if folder has id equal to source file id
    const folderIndex = list.findIndex(fld => fld.id === fileId)
    if (folderIndex !== -1) throw new Error("You cannot move a folder")


    // if destination has id equal to any file id
    const destinationIndex = list.findIndex(fld => fld.files.some(file => file.id === destinationId))
    if (destinationIndex !== -1) throw new Error("You cannot specify a file as the destination")

    // any other case
    throw new Error("File not found")
}


// this function will find all the necessary indices 
function findIndicesByFileId(list: Folder[], sourceId: string, destinationId: string): [sourceFolderIndex: number, destinationFolderIndex: number, fileIndex: number,] {
    // finding folder id (is any folder that has the file with the serched id inside)
    const folderIndex = list.findIndex(fld => fld.files.some(file => file.id === sourceId))

    //finding destination folder
    const destinationFolderIndex = list.findIndex(fld => fld.id === destinationId)

    //if any search fails recognizeFileSearchError function runs
    if (folderIndex === -1 || destinationFolderIndex === -1) recognizeFileSearchError(list, sourceId, destinationId)


    // finding file index inside the designed folder
    const fileIndex = list[folderIndex].files.findIndex(file => file.id === sourceId)

    // returning all the indices
    return [folderIndex, destinationFolderIndex, fileIndex]
}

// move function
function move(list: Folder[], source: string, destination: string): Folder[] {
    // cloning the list
    const listToEdit = [...list];


    // find all necessary indices with the findIndicesByFileId function
    const [sourceFolderIndex, destinationFolderIndex, fileIndex] = findIndicesByFileId(list, source, destination)

    // getting the file to move out using Array.Prototype.splice() (which returns the array of deleted elements so, since I am removing only one element the array will always be of size 1)
    const fileToMove = listToEdit[sourceFolderIndex].files.splice(fileIndex, 1)[0]

    // pushing the file to move into the destination
    listToEdit[destinationFolderIndex].files.push(fileToMove)

    // returning the updated list
    return listToEdit

}


console.log(move(list, "4", "6"))

 

Комментарии:

1. Большое вам спасибо за ваши усилия и ответ, но когда я запускаю тест, он говорит: «‘destinationFolderIndex’ относится к значению, но используется здесь как тип. Вы имели в виду «тип destinationFolderIndex»?». Как я могу с этим справиться? Можете ли вы также запустить файл спецификации?

2. не могли бы вы предоставить код, который вы написали? Я тестировал на typescript 4.3.5, и все прошло хорошо, может быть, вы скопировали/использовали что-то не так

3.Я полностью копирую/вставляю код и запускаю тест сейчас, в нем написано «Не удается найти имя» sourceFolderIndex». » и «»destinationFolderIndex» относится к значению, но используется здесь как тип. Вы имели в виду «тип destinationFolderIndex»? » ibb.co/Pt77gvB ibb.co/vV3vwMB ibb.co/RCbVTcL

4. Я настроил отправляющее поле с файлом спецификации, и все работает нормально, здесь вы можете найти настройки: codesandbox.io/s/typescript-forked-0w6k7?file=/src/move.test.ts