Невозможно присвоить значение ключа объекта в массиве объектов

Вопрос или проблема

Я получаю следующую ошибку:

Тип ‘string | number | boolean’ не может быть присвоен типу ‘never’.

при присвоении внутри функции mutateData. Я не совсем понимаю, почему, потому что данные инициализируются как пустой массив с правильным типом.

type FileObject = {
    name: string
    path: string
    returnStatus: number
    dataPrepared: boolean
}

type Keys = keyof FileObject

type KeyValue = {
    [key in Keys]: {key: key, value: FileObject[key]}
}[Keys]

type Mutation = {
    index: number
} & KeyValue

const data: FileObject[] = []

function mutateData(input: Mutation) {
    data[input.index][input.key] = input.value
}

Playground

Я считаю, что вышеуказанное решение должно работать, поскольку тип Mutation состоит из индекса и правильных объединенных типов пар ключ/значение.

Ответ или решение

Ошибка, с которой вы столкнулись, возникает из-за того, что TypeScript не может правильно сопоставить типы при выполнении операции присваивания в вашем коде. Давайте разберём вашу проблему шаг за шагом и предложим решение.

Причина ошибки

Тип KeyValue, который вы используете в типе Mutation, не определяет key и value как соответствующие типы, которые могут быть использованы для доступа к объекту FileObject. Из-за этого TypeScript считает, что присвоение значения к data[input.index][input.key] не подходит с точки зрения типов, и выдаёт ошибку, сообщая, что тип string | number | boolean не совпадает с типом never.

Решение проблемы

Чтобы исправить данное поведение, вы можете использовать перегрузку типов для функции mutateData. Это позволит вам явно указать типы для ключа и значения, что упростит управление типами. Таким образом, мы сможем сделать следующее:

  1. Убедиться, что input.key корректно понимается как один из ключей FileObject.
  2. Избежать конфликта типов при присвоении значений.

Вот исправленный код:

type FileObject = {
    name: string;
    path: string;
    returnStatus: number;
    dataPrepared: boolean;
}

type Keys = keyof FileObject;

type KeyValue<K extends Keys> = {
    key: K;
    value: FileObject[K];
}

type Mutation<K extends Keys> = {
    index: number;
} & KeyValue<K>;

const data: FileObject[] = [];

// Функция принимает в качестве параметра объект Mutation с типом K
function mutateData<K extends Keys>(input: Mutation<K>) {
    data[input.index][input.key] = input.value;
}

// Пример использования
data.push({
    name: "example.txt",
    path: "/path/to/example.txt",
    returnStatus: 200,
    dataPrepared: true
});

// Теперь функция может присваивать значения корректно
mutateData({ index: 0, key: "name", value: "newname.txt" });
mutateData({ index: 0, key: "returnStatus", value: 404 });

Комментарии к исправлениям

  1. Перегрузка типов: Мы добавили обобщение <K extends Keys> к Mutation и mutateData, что позволяет TypeScript выяснить, какие конкретные ключи и соответствующие значения используются при присвоении.

  2. Пример использования: В конце кода вы можете видеть пример добавления объекта в массив data и вызов mutateData, который корректно обновляет значения.

Таким образом, это должно устранить вашу проблему с ошибкой типов и обеспечить корректность работы программы. Если у вас есть дополнительные вопросы, не стесняйтесь спрашивать.

Оцените материал
Добавить комментарий

Капча загружается...