Typescript: добавить типизацию для объекта ответа, содержащего как сигнатуру индекса, так и пары ключей - PullRequest
1 голос
/ 25 июня 2019

Я не уверен, какой лучший способ добавить набор текста для этого объекта ответа, который я получаю от бэкэнд-службы:

{
    de49e137f2423457985ec6794536cd3c: {
        productId: 'de49e137f2423457985ec6794536cd3c',
        title: 'item 1',
    },
    d6623c1a2b843840b14c32685c212395: {
        productId: 'd6623c1a2b843840b14c32685c212395',
        title: 'item 2',
    },
    ids: [
        'de49e137f2423457985ec6794536cd3c',
        'd6623c1a2b843840b14c32685c212395',
    ],
}

Содержит массив идентификаторов элементов string [] а также подпись индекса [id: string]: Item .

Кажется, что для Typescript не обязательно иметь подпись индекса и массив в одном интерфейсе.Например:

interface ItemList {
    [id: string]: Item;
    ids: string[];
}

Я знаю, что при использовании подписи индекса другие свойства должны возвращать тот же тип.Я новичок в Typescript и немного не уверен, как работать с этими данными, не перемещая ids из объекта item?

interface ItemList {
    [id: string]: Item;
    ids: string[];
}
interface Item {
    productId: string;
    title: string;
}

const item: ItemList = {
    de49e137f2423457985ec6794536cd3c: {
        productId: 'de49e137f2423457985ec6794536cd3c',
        title: 'item 1',
    },
    d6623c1a2b843840b14c32685c212395: {
        productId: 'd6623c1a2b843840b14c32685c212395',
        title: 'item 2',
    },
    ids: [
        'de49e137f2423457985ec6794536cd3c',
        'd6623c1a2b843840b14c32685c212395',
    ],
};
console.log(item.ids.map((id: string) => item[id]));

Ошибка

Свойство 'map' не существует для типа 'Item |string [] '.

Свойство' map 'не существует для типа' Item '.

1 Ответ

2 голосов
/ 25 июня 2019

Простым решением здесь является использование типа пересечения:

type ItemList = {
    [id: string]: Item;
} & {
    ids: string[];
}
interface Item {
    productId: string;
    title: string;
}

const item: ItemList = Object.assign({ // Can't build the object directly 
    de49e137f2423457985ec6794536cd3c: {
        productId: 'de49e137f2423457985ec6794536cd3c',
        title: 'item 1',
    },
    d6623c1a2b843840b14c32685c212395: {
        productId: 'd6623c1a2b843840b14c32685c212395',
        title: 'item 2',
    }
}, {
    ids: [
        'de49e137f2423457985ec6794536cd3c',
        'd6623c1a2b843840b14c32685c212395',
    ],
});
console.log(item.ids.map((id: string) => item[id]));

Тип пересечения допускает несовместимую именованную комбинацию свойство - индекс. (Обратите внимание, что это не является строго типобезопасным, поскольку item['ids'] не возвращает Item, как ожидалось, но в данном случае это выглядит как достойный компромисс)

...