如何在 TypeScript 中添加索引签名
How to add index signature in TypeScript
我正在尝试将 reduce 与 Typescript 结合使用来达到传入消息的总数。我对如何添加索引签名感到困惑。我不断收到错误消息:“元素隐式具有 '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 问题中“只是一个学生”的回答:对数组中的值进行分组和计数
,我有以下内容。
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)
添加字符串给我一个错误"Element implicitly has an 'any' type because index expression is not of type 'number'."
添加 newA[time].toString()
给我错误,"The left-hand side of an assignment expression must be a variable or a property access."
如果我理解你的话,你需要为对象创建接口...
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);
.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
,但您可能希望针对您的特定情况使其更加具体。
数组的正确类型是:
Array<{time: string}>
或:
{time: string}[]
或:
{[key: number]: {time: string}}
您必须添加具有索引签名的类型。例如
const myObj: {[key: string]: string} = {
someProperty: 'someValue',
};
{[key: string]: any}
告诉 Typescript 这个对象有一个字符串类型的索引签名。
原始问题的答案
主要警告是 reduce
累加器值输入不正确。
原代码:
const result = data.reduce(someLogicCallback, {})
需要按以下方式进行:
const accumulator: {[key: string]: number} = {}
const result = data.reduce(someLogicCallback, accumulator)
其他可能的注意事项
这部分可能对以后偶尔使用 google 的人有所帮助。
我来这里是为了解决类似的问题,但在我的例子中,我有一个已经预定义类型的对象
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] };
});
我正在尝试将 reduce 与 Typescript 结合使用来达到传入消息的总数。我对如何添加索引签名感到困惑。我不断收到错误消息:“元素隐式具有 '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 问题中“只是一个学生”的回答:对数组中的值进行分组和计数 ,我有以下内容。
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)
添加字符串给我一个错误"Element implicitly has an 'any' type because index expression is not of type 'number'."添加
newA[time].toString()
给我错误,"The left-hand side of an assignment expression must be a variable or a property access."
如果我理解你的话,你需要为对象创建接口...
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);
.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
,但您可能希望针对您的特定情况使其更加具体。
数组的正确类型是:
Array<{time: string}>
或:
{time: string}[]
或:
{[key: number]: {time: string}}
您必须添加具有索引签名的类型。例如
const myObj: {[key: string]: string} = {
someProperty: 'someValue',
};
{[key: string]: any}
告诉 Typescript 这个对象有一个字符串类型的索引签名。
原始问题的答案
主要警告是 reduce
累加器值输入不正确。
原代码:
const result = data.reduce(someLogicCallback, {})
需要按以下方式进行:
const accumulator: {[key: string]: number} = {}
const result = data.reduce(someLogicCallback, accumulator)
其他可能的注意事项
这部分可能对以后偶尔使用 google 的人有所帮助。
我来这里是为了解决类似的问题,但在我的例子中,我有一个已经预定义类型的对象
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] };
});