[英]Problems typing functions using typescript generics
Case #1情况1
I am getting error:我收到错误:
Property 'name' does not exist on type 'T'
类型“T”上不存在属性“名称”
function test<T>(arr:Array<T>, item:T) {
const idxReplaced = arr.findIndex(element=> element.name === item.name)
return {
...arr.slice(0, idxReplaced),
...arr.slice(idxReplaced+1)
}
}
interface IItem {
name: number
}
console.log(test<IItem>([{name:1},{name:3}], {name: 3}))
Case #2案例#2
I want to change every name property in object array according its name.我想根据其名称更改 object 数组中的每个名称属性。
I am getting errors:我收到错误:
Element implicitly has an 'any' type because expression of type 'any' can't be used to index type 'ICurrentItem'
元素隐式具有“any”类型,因为“any”类型的表达式不能用于索引类型“ICurrentItem”
and和
Property 'name' does not exist on type 'IItem'.
类型“IItem”上不存在属性“名称”。
interface IItem {
user: string,
}
interface ICurrentItem {
[key: string]: IItem
}
function test<IItem>(arr:Array<IItem>, item:IItem) {
return arr.reduce((acc:ICurrentItem,el:IItem)=> {
acc[el.user] = item[el.user]
return acc
},{})
}
console.log(test([{user:'info'},{user:'test'}], {user: 'some info'}))
You can test it here: Typescript Playground你可以在这里测试它: Typescript Playground
@kaya3's comment is correct. @kaya3 的评论是正确的。 Your function assumes that your array elements and your
item
variable (both type T
) will have a .name
property.您的 function 假定您的数组元素和
item
变量(均为T
类型)将具有.name
属性。 So you must ensure that all possible types for T
include at least a name
.因此,您必须确保
T
的所有可能类型至少包含一个name
。
function test1<T extends { name: any }>(arr: Array<T>, item: T) {
const idxReplaced = arr.findIndex(element => element.name === item.name)
return [
...arr.slice(0, idxReplaced),
...arr.slice(idxReplaced + 1)
]
}
You don't need to set the generic here because it is inferred as <{name: number}>
based on the arguments.您不需要在此处设置泛型,因为它根据 arguments 推断为
<{name: number}>
。
console.log(test1([{ name: 1 }, { name: 3 }], { name: 3 }))
function test<IItem>(arr:Array<IItem>, item:IItem) {
This right here shows a misunderstanding of generic type parameters.这在这里显示了对泛型类型参数的误解。 You can use any name for the generic type and
<IItem>
here is basically <T>
with another name.您可以为泛型类型使用任何名称,这里的
<IItem>
基本上是带有另一个名称的<T>
。 It is a local type variable that bears no relation to the interface IItem
.它是一个与
interface IItem
的局部类型变量。
I suspect what you meant to do was something like this, where the generic type must extend {user: string}
:我怀疑你的意思是这样的,泛型类型必须扩展
{user: string}
:
function test2<T extends IItem>(arr: Array<T>, item: T) {
Or to not have it be generic at all, and simply add types to the arguments:或者根本不让它通用,只需将类型添加到 arguments:
function test2(arr: Array<IItem>, item: IItem) {
We are building an object acc
where the key is a string
from the item's user
property and the value is an item
.我们正在构建一个 object
acc
,其中键是项目user
属性的string
,值是item
。 You've got that part typed correctly.您已经正确输入了该部分。 It's fine to access
acc[el.user]
because acc
has a string index.访问
acc[el.user]
很好,因为acc
有一个字符串索引。
But what are you trying to to do with item[el.user]
?但是你想用
item[el.user]
做什么? el.user
is the username string
and item
is an IItem
. el.user
是用户名string
,而item
是IItem
。 It does not have a property that corresponds to the user
value.它没有与
user
值对应的属性。
In your example:在您的示例中:
console.log(test2([{ user: 'info' }, { user: 'test' }], { user: 'some info' }))
You would be accessing ({ user: 'some info' }).info
and ({ user: 'some info' }).test
.您将访问
({ user: 'some info' }).info
和({ user: 'some info' }).test
。 Typescript is right to warn you that those don't exist. Typescript 是正确的警告您这些不存在。
I'm genuinely not sure what you are trying to achieve here.我真的不确定您要在这里实现什么。 If you meant to turn an array of items into an object keyed by the username then you don't need a second argument
item
for that.如果您打算将一组项目转换为由用户名键入的 object,那么您不需要第二个参数
item
。 That would be:那将是:
interface IItem {
user: string,
}
interface ICurrentItem<T extends IItem> {
[key: string]: T
}
function test2<T extends IItem>(arr: Array<T>) {
return arr.reduce((acc: ICurrentItem<T>, el: T) => {
acc[el.user] = el
return acc
}, {})
}
console.log(test2([{ user: 'info' }, { user: 'test' }]))
Typescript Playground Link Typescript 游乐场链接
edit: "I want to change every name property in object array according its name."编辑: “我想根据名称更改 object 数组中的每个名称属性。”
I think maybe you want map instead of reduce ?我想也许你想要map而不是reduce ?
This code replaces the user
property of the array elements with the user property from item.user
("some info").此代码将数组元素的
user
属性替换为item.user
中的用户属性(“一些信息”)。
function test<T extends IItem>(arr: Array<T>, item: T) {
return arr.map(el => ({ ...el, user: item.user }));
}
console.log(test([{ user: 'info' }, { user: 'test' }], { user: 'some info' }))
// output: [{ "user": "some info" }, { "user": "some info" }]
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.