繁体   English   中英

在Typescript中映射类型的索引签名

[英]Index signature for a mapped type in 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上分别缺少索引签名。 但是我应该如何为映射类型添加索引签名呢?

错误是有意义的,因为您不能将string键分配给具有特定键没有索引签名的接口(索引签名是指示接口应该为未知键返回的指令,即string键)。

因此,您应该像这样更改您的代码:

Object.entries(scale).forEach(([key, value]: [Scales /* EDIT1 */, number]) => {
    sizing1[key] = `${value * 1.6}rem`
})
const sizing2: TSizing2 = Object.assign(
    {},
    ...Object.keys(scale).map((k) => ({ [k]: `${scale[k as Scales] /*EDIT2*/ * 1.6}rem` })),
)

我希望第一次编辑(EDIT1)很清楚。 第二个(EDIT2)是一个必要的恶,因为即使参数已知类型, Object.keys仍然只返回string []。

问题不在于如何定义TSizing1TSizing2 ,而是在调用Object.prototype.entriesObject.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一些数据。 信息丢失了。

为了弥补这种损失,断言他们的类型是你所知道的。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM