如何在 TypeScript 中添加索引签名
Posted
技术标签:
【中文标题】如何在 TypeScript 中添加索引签名【英文标题】:How to add index signature in TypeScript 【发布时间】:2018-07-24 04:32:39 【问题描述】:我正在尝试使用带有 Typescript 的 reduce 来达到传入消息的总数。我对如何添加索引签名感到困惑。我不断收到错误消息:“元素隐式具有 'any' 类型,因为类型 '' 没有索引签名。”在变量 newArray 和 counts[k] 上。我已经阅读了几个类似的问题,但还没有弄清楚如何将它们应用于我的特定场景。我是 javascript 和 TypeScript 的新手。
这是我的数组:
var data = [
time: '9:54' ,
time: '9:54' ,
time: '9:54' ,
time: '9:55' ,
time: '9:55' ,
time: '9:55' ,
time: '9:55' ,
time: '9:56' ,
time: '9:56' ,
time: '9:56' ,
time: '9:56' ,
time: '9:57' ,
time: '9:57' ,
time: '9:57' ,
time: '9:57' ,
time: '9:57'
];
这就是我需要我的数组在图表图中使用的方式:
var dataWithCounts = [
time: '9:54', messages: 3 ,
time: '9:55', messages: 4 ,
time: '9:56', messages: 4 ,
time: '9:57', messages: 5
];
借助来自 Stack Overflow 问题的“只是一个学生”的回答:Group and count values in an array ,我有以下内容。
var counts = data.reduce((newArray, item) =>
let time = item.time;
if (!newArray.hasOwnProperty(time))
newArray[time] = 0;
newArray[time]++;
return newArray;
, );
console.log(counts);
var countsExtended = Object.keys(counts).map(k =>
return time: k, messages: counts[k] ;
);
console.log(countsExtended);
在哪里以及如何声明索引签名?以下是我尝试过的各种方法。
let newArray: [time: string] ;
并收到重复标识符错误。
将字符串添加到参数var counts = data.reduce((newA:string, item)
给我一个错误“元素隐式具有'any'类型,因为索引表达式不是'number'类型。”
添加newA[time].toString()
给我错误,“赋值表达式的左侧必须是变量或属性访问。”
【问题讨论】:
不是打字员,但会猜测这是因为您没有向reduce
回调声明第三和第四个参数。传递给reduce
的函数得到 1。累加器。 2. 数组中的当前项。 3.当前指数。 4.原始数组。
在您的 tsconfig.json 文件中将 noImplicitAny
设置为 false。
【参考方案1】:
原始问题的答案
主要的警告是reduce
累加器值没有正确输入。
原码:
const result = data.reduce(someLogicCallback, )
需要通过以下方式进行:
const accumulator: [key: string]: number =
const result = data.reduce(someLogicCallback, accumulator)
其他可能的注意事项
这部分可能对后来偶尔的谷歌人有所帮助。
我来这里是为了解决类似的问题,但在我的情况下,我有一个对象已经预定义了类型
typeof someObject // predefinedType
type predefinedType =
someKey: number;
otherKey: number;
当我尝试从该对象中提取条目时出现index signature is missing in type predefinedType
错误
const entries = Object.entries<number>(someObject);
显而易见的解决方案是进行类型断言
type TypedIndexObj = [key: string]: number
const entries = Object.entries<number>(someObject as TypedIndexObj);
但这太严格了,因为它总是将someObject
的值类型断言为number
,这可能会随着时间而改变。
我想出的添加此类对象的索引类型的最佳方法是使用keyof
语法
type TypedIndexObj = [key in keyof typeof someObject]:(typeof someObject)[key]
const entries = Object.entries<number>(someObject as TypedIndexObj);
参考:原始问题的更正代码
这是原始问题中代码的完全键入的更正版本:
const accumulator: [key: string]: number =
const counts = data.reduce((_accumulator, item) =>
const time = item.time;
// no error on the next line
if (!_accumulator.hasOwnProperty(time))
_accumulator[time] = 0;
_accumulator[time]++;
return _accumulator;
, accumulator);
const countsExtended = Object.keys(counts).map(k =>
return time: k, messages: counts[k] ;
);
【讨论】:
【参考方案2】:您必须添加具有索引签名的类型。例如。
const myObj: [key: string]: string =
someProperty: 'someValue',
;
[key: string]: any
告诉 Typescript 这个 obj 有一个字符串类型的索引签名。
【讨论】:
【参考方案3】:您的数组的正确类型是:
Array<time: string>
或:
time: string[]
或:
[key: number]: time: string
【讨论】:
【参考方案4】:.reduce
调用中的累加器类型几乎肯定是问题所在。因为它只是作为 给出的,所以它的类型就是这样推断的,而
类型没有索引签名。您可以通过强制转换初始值来解决此问题,以便它包含签名:
var counts = data.reduce((newArray, item) =>
let time = item.time;
if (!newArray.hasOwnProperty(time))
newArray[time] = 0;
newArray[time]++;
return newArray;
, as [key: string]: any); // <-- note the cast here
我提供了索引签名类型any
,但您可能希望针对您的特定情况使其更具体。
【讨论】:
谢谢Crice!完美运行【参考方案5】:如果我理解你,你需要为对象创建接口...
interface counts_t
time?: string,
messages?: number
var data: counts_t[] = [
time: '9:54' ,
time: '9:55' ,
time: '9:56' ,
time: '9:57'
];
var counts = data.reduce((newArray:counts_t, item:counts_t) =>
let time = item.time;
if (!newArray.hasOwnProperty(time))
newArray[time] = 0;
newArray[time]++;
return newArray;
, );
console.log(counts);
var countsExtended: counts_t[] = Object.keys(counts).map(k =>
return time: k, messages: counts[k] ;
);
console.log(countsExtended);
【讨论】:
谢谢'我曾经和一只熊搏斗'。这可能是另一种解决方法。 Crice 上面的回答奏效了。很棒的用户名顺便说一句以上是关于如何在 TypeScript 中添加索引签名的主要内容,如果未能解决你的问题,请参考以下文章
如何创建具有索引签名和不同类型的固定属性的 TypeScript 接口?