@AlexWeb6667
Web-дизайнер с опытом FullStack разработки

Как правильно обрабатывать многомерные массивы в typeScript?

Всем доброго времени суток, столкнулся с проблемой, у меня свойство может быть как просто массивом, так и многомерным массивом. Вроде бы все условия описал верно, все работает, но ts почему-то ругается. Не подскажите как правильно описать подобную ситуацию чтоб не было ошибки

Сама ошибка
Argument of type '{ [x: string]: string; }' is not assignable to parameter of type '{ [key: string]: string; } & { [key: string]: string; }[]'.
Type '{ [x: string]: string; }' is missing the following properties from type '{ [key: string]: string; }[]': length, pop, push, concat, and 28 more.


let errorMessage = 'error',
     controlName = 'test'
if (formIndex !== null) {
            form.formParams.errorList[formIndex] = {...form.formParams.errorList[formIndex], [controlName]: errorMessage}
        } else {

            if (Array.isArray(form.formParams.errorList)) {

                form.formParams.errorList.push({[controlName]: errorMessage})
            }

        }


Как я типизировал errorList в котором ошибка
errorList?: {[key: string]: string}[] | {[key: string]: string}[][]
  • Вопрос задан
  • 184 просмотра
Пригласить эксперта
Ответы на вопрос 2
@xenonhammer
дженериик, может поможет.
type TArray<T> = T extends { [key: string]: string } ? {[key: string]: string} :  {[key: string]: string}[];


Лучше если у вас errorList всегда будет одномерным, многомерные массивы в TS вообще слабая сторона, будут потом проблемы, и все страшно запутается
Ответ написан
Комментировать
bingo347
@bingo347 Куратор тега TypeScript
Crazy on performance...
Проблема в ...form.formParams.errorList[formIndex]
Давайте по порядку:
// допустим у нас есть следующие переменные с типами:
let obj: Obj;
let value: T;

// мы их собираем в такой объект:
const newObj = { ...obj, k: value };
тип для newObj компилятор будет выводить из контекста и получит Obj & { k: T }, ровно из того, что мы объединяем эти сущности.

Усложним пример:
let objs: Obj[];
let value: T;
let key: string;

const newObj = { ...objs[1], [key]: value };
Тип на выходе будет ужеObj & { [key: string]: string }, хотя objs на это раз у нас массив, компилятор видит, что мы берем индекс.

Что будет, если objs вместо простого Obj[] у нас будет Obj[] | Obj[][]?
Сначала мы берем значение по индексу из objs - эта операция вернет тип Obj | Obj[].
После мы разворачиваем его через spread в объект и дописываем значение по индексу, получаем тип:(Obj | Obj[]) & { [key: string]: string }, тут еще Важно понимать, что типы в TS - это чистая математика, и данный тип полностью равносилен такому:
(Obj & { [key: string]: string }) | (Obj[] & { [key: string]: string })

А что, если Obj - это тоже { [key: string]: string }? Мы сможем свернуть тип, упростив уравнение на типах:
(Obj & Obj) | (Obj[] & Obj)
(Obj) | (Obj[] & Obj)
(Obj & Obj[]) | (Obj & Obj)
(Obj & Obj[]) | (Obj)
Obj & Obj[]
И это именно тот тип, который получил у Вас компилятор
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы