#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