почему typeScript допускает пустой массив?

по идее он же должен ругаться на unknownLengthResArray: [] ведь в методе указано что это массив объектов которые должны иметь key

const args = {
    unknownLengthResArray: [],
    t,
    keyName: 'service',
    namespace: 'services'
}

const sectionBody = unknownLengthDatagridRowSectionBody(args)


interface IInnerObject {
    key: string;
}

type TArgsType = {
    unknownLengthResArray?: IInnerObject[];
    t: any;
    keyName: string;
    namespace: string;
}

type TReturnType = Dictionary<string>[];

export const unknownLengthDatagridRowSectionBody = ({
    unknownLengthResArray,
    t,
    keyName,
    namespace
}: TArgsType): TReturnType => {
    const sectionBody = []
    if(unknownLengthResArray?.length) {
        let section = {}
        let denominator = 3
        unknownLengthResArray.forEach(({ key }, i) => {
            const sectionInfo = {
                [`${t(keyName)} ${i+1}`]: t(`${namespace}:${key}`)
            }
            while(i < denominator){
                section = {...section, ...sectionInfo}
                return
            }
            sectionBody.push(section)
            section = {}
            denominator += denominator
        })
    }
    return sectionBody
}

Ответы (1 шт):

Автор решения: yar85

почему typeScript допускает пустой массив?

Потому что пустой массив все же является массивом: когда тип самой переменной со значением [] описан как обычный массив - соответствие типов вполне соблюдается, независимо от типа элементов массива.

по идее он же должен ругаться на unknownLengthResArray: [] ведь в методе указано что это массив объектов которые должны иметь key

Это ожидание типизации "пустоты", отсутствия значения, которое типизировать невозможно по определению (за исключением спецтипа never, который тут по-моему неприменим).
Проще говоря: когда в массиве нет содержимого - нечего проверять на соответствие типов.


Как можно объявить тип непустого массива типизированных объектов:

interface IInnerObject {
  key: string;
}

interface INonEmptyArray<T> {
  0: T;
  [key: number]: T;
}

type ArrayOfInnerObject = Array<IInnerObject> & INonEmptyArray<IInnerObject>;

TS Playground

Индексы js-массива непрерывны, поэтому массив с как минимум одним значением всегда имеет элемент с индексом 0.

При этом, если допустить "пропуск" в значениях, (например) при массиве из двух элементов добавив еще один по индексу 3, сработает проверка типов - т.е., должна возникать ошибка(а фиг там) TS почему-то не могёт/не хочет проверять тип значений в промежуточных индексах (тут это индекс 2 со значением undefined), такой нюанс надо учитывать: в идеале, не допускать пропусков, следя за своими константами и явными присваиваниями по индексу; и фильтруя/преобразуя поступающие извне (например, от бэкэнда) входные данные, которые TS не сможет проверить в любом случае.

→ Ссылка