Typescript:为包含索引签名和密钥对的响应对象添加类型

Typescript:为包含索引签名和密钥对的响应对象添加类型,typescript,object,types,key-pair,index-signature,Typescript,Object,Types,Key Pair,Index Signature,我不确定为从后端服务接收的此响应对象添加typescript类型的最佳方法: { de49e137f2423457985ec6794536cd3c: { productId: 'de49e137f2423457985ec6794536cd3c', title: 'item 1', }, d6623c1a2b843840b14c32685c212395: { productId: 'd6623c1a2b843840b14c32

我不确定为从后端服务接收的此响应对象添加typescript类型的最佳方法:

{
    de49e137f2423457985ec6794536cd3c: {
        productId: 'de49e137f2423457985ec6794536cd3c',
        title: 'item 1',
    },
    d6623c1a2b843840b14c32685c212395: {
        productId: 'd6623c1a2b843840b14c32685c212395',
        title: 'item 2',
    },
    ids: [
        'de49e137f2423457985ec6794536cd3c',
        'd6623c1a2b843840b14c32685c212395',
    ],
}
它包含一个项目id数组string[]以及索引签名[id:string]:项目

Typescript似乎不喜欢在单个接口中包含索引签名和数组。例如:

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

我知道当使用索引签名时,其他属性需要返回相同的类型。我是Typescript新手,我有点不确定如何在不将ID移出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]));
错误

类型“Item | string[]”上不存在属性“map”


属性“map”在类型“Item”上不存在。

这里的简单修复方法是使用交叉点类型:

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['id']
不会按预期返回
item
,但这似乎是一个不错的折衷方案)

Titian,感谢您的快速响应,这为我带来了好处。你能解释一下使用Object.assign背后的逻辑吗?使用交集时,两种对象类型是否需要源自与交集类型匹配的单独对象?如果没有它,我将收到错误:无法分配给类型“ID&items”