typescript - Typescript 中映射类型的索引签名
问题描述
type Scales = 'xxs' | 'xs' | 's' | 'm' | 'l' | 'xl' | 'xxl'
type TScale = { [k in Scales]: number }
type TSizing1 = { [k in Scales]?: string }
type TSizing2 = { [k in Scales]: string }
const scale: TScale = {
xxs: 1 / 8,
xs: 1 / 4,
s: 1 / 2,
m: 1,
l: 2,
xl: 4,
xxl: 8,
}
const sizing1: TSizing1 = {}
Object.entries(scale).forEach(([key, value]: [string, number]) => {
sizing1[key] = `${value * 1.6}rem`
})
const sizing2: TSizing2 = Object.assign(
{},
...Object.keys(scale).map(k => ({ [k]: `${scale[k] * 1.6}rem` })),
)
sizing1 和 sizing2 都会出错,因为 TSizing1 和 TScale 分别缺少索引签名。但是我应该如何将索引签名添加到映射类型?
解决方案
问题不在于如何定义TSizing1
or ,而是在调用orTSizing2
时如何处理对象类型。Object.prototype.entries
Object.prototype.keys
解决方案
告诉 TypeScript 在对对象进行操作时使用缩小的特定类型。替换这些:
Object.entries(scale)
Object.keys(scale)
和那些:
(Object.entries(scale) as [Scales, number][])
(Object.keys(scale) as Scales[])
所以解决方案看起来像:
(Object.entries(scale) as [Scales, number][]).forEach(([key, value]) => {
sizing1[key] = `${value * 1.6}rem`;
});
const sizing2: TSizing2 = Object.assign(
{},
...(Object.keys(scale) as Scales[]).map(k => ({ [k]: `${scale[k] * 1.6}rem` })),
);
解释
TypeScript 在推断对象类型时非常糟糕。即使我们确切地知道是什么键scale
(它们的定义非常明确Scales
),TypeScript 仍会将它们视为只是一些类型的数据string
。信息丢失。
为了弥补这种损失,断言它们的类型是你所知道的。
推荐阅读
- json - 使用jq将文件中的数组元素添加到其他文件的json数组中
- r - 如何减去存储在R中两个列表中的向量?
- java - 自定义样式中的secondaryTextColor 不起作用
- html - 当我将页面方向更改为 rtl 时移动侧面导航栏
- javascript - 如何停止去抖动的 Rxjs Observable?
- cron - 如何使用 cron 运行 linux 命令
- ios - 下载启用 Fairplay 的视频时获取服务器播放上下文时出错
- javascript - 有没有办法在 Leaflet.js 中找到多边形的交集?
- php - Symfony 4 make:migration 在 ManyToMany 时不起作用
- javascript - 如何使用 mongoose 在循环中迭代 mongoose 返回的文档数组?