在尝试为reduce
方法内的数据设置类型时,我在angular应用程序中遇到了typescript错误。
error TS7053: Element implicitly has an 'any' type because expression of type 'string' can't be used to index type 'ICar'.
No index signature with a parameter of type 'string' was found on type 'ICar'.
后端侧向我发送以下对象数组,我将其传递给getCarProperty
函数:
[
{
created: null
id: "124545484822"
details: {
name: "Ford focus"
number: "128888"
}
status: "working"
usedFrom: null
usedUntil: null
},
{
created: null
id: "99525484827"
details: {
name: "Honda Accord"
number: "598402"
}
status: "working"
usedFrom: null
usedUntil: null
}
]
以下是功能的样子:
getCarProperty = (obj: ICar, path: string): any => {
if (path.indexOf('.') > -1) {
return path.split('.').reduce((o: ICar, p: string) => {
return o && o[p]; <----- HERE IS THE ISSUE
}, obj);
}
return Array.from(path).reduce((o: ICar, p: string) => {
return o && o[p]; <------ Here is the issue
}, obj);
};
当details.name
属性通过path
参数时,我可以得到name
属性的值(例如"Ford focus"one_answers"Honda Accord"(。
以下是用于此数据的接口:
export interface IDetail {
name: string;
number: string;
}
export interface IContract {
created: string;
id: string;
detail: IDetail;
status: string;
usedFrom: string;
usedUntil: string;
}
我尝试应用不同的解决方案,如[propName askeyofICar]或设置泛型类型,但都没有成功。那么,这里出了什么问题?
感谢您的帮助。
问题是reduce回调期望一个符合ICar
接口的对象,这仅在reduce回叫的第一次迭代中为真,在reduce回调的下一次迭代中,您将不再接收到ICar
类型的对象(仅IDetails
或string
(,因此约束失败。基本上,每个迭代的返回都返回一个不同的类型,这就是为什么你不能在那里使用特定的类型,但在某些情况下你可以使用类型的并集。
要解决您的问题,只需将ICar
类型替换为any
,如下所示。我认为这没有任何问题,因为您仍在检查getCarProperty
函数参数。
getCarProperty = (obj: ICar, path: string): any => {
if (path.indexOf('.') > -1) {
return path.split('.').reduce((o: any, p: string) => {
return o && o[p];
}, obj);
}
return Array.of(path).reduce((o: any, p: string) => {
return o && o[p];
}, obj);
};
如果你真的想保留类型,并且不想使用any
,你可以尝试下面的函数,但我看不出有多大优势,因为你已经在键入函数参数了。
function getCarProperty(obj: ICar, path: string): any {
type CarOrDetailType = ICar | IDetail; // <-- All the possibilities for the reduce `previousValue` callback parameter. If the ICar interface changes, you might need to adjust this.
type CarOrDetailKey = keyof CarOrDetailType;
if (path.indexOf('.') > -1) {
const typedPath = path.split('.') as Array<CarOrDetailKey>;
return typedPath.reduce((o: CarOrDetailType, p: CarOrDetailKey): any => {
return o && o[p];
}, obj);
}
const typedPath = Array.of(path) as Array<CarOrDetailKey>;
return typedPath.reduce((o: CarOrDetailType, p: CarOrDetailKey) => {
return o && o[p];
}, obj);
}
我在你的代码中发现了另外两个问题,但可能是你复制错误,它们是:
- 您的模拟数据在每个属性后都没有comas,因此它没有有效的语法
- 您在字符串上使用了
Array.from(path)
,但可能想要Array.of(path)