我想做这样的事情:
type Foo = {
name: string;
value: any;
}
const myFoos: Foo[] = [
{
name: "hello",
value: 1,
},
{
name: "world",
value: "bar"
}
];
function createObjectFromFooArray(foos: Foo[]) : Record<string, Foo> { //Need to change the return type
return foos.reduce((acc, cur) => {
return {
...acc,
[cur.name]: cur
}
}, {});
}
const objectFoos = createObjectFromFooArray(myFoos);
console.log(objectFoos.hello);
console.log(objectFoos.aaa); //Should error
也就是说-给定一个Foo
s数组,我想创建一个Foo
s的映射对象,并且我希望该对象只包含属于name
属性的索引原始Foo
数组的元素。我该怎么做?
答案 0 :(得分:1)
这里有一些问题。一种是您必须拒绝将myFoos
注释为Foo[]
,因为这会使编译器将name
属性扩展到string
,而您需要跟踪{{3 }},例如"hello"
和"world"
。相反,您应该使用string literal types之类的字词,以使myFoos
的类型尽量缩小:
const myFoos = [
{
name: "hello",
value: 1,
},
{
name: "world",
value: "bar"
}
] as const;
然后,您可以使createObjectFromFooArray
的元素类型为T
的类型foos
中的T
是通用的,其中Foo
限于name
,但可以更具体。并且返回类型可以是条件映射类型,该条件映射类型迭代键的T
的{{1}}属性,并为每个属性值提取相应的value
属性:
function createObjectFromFooArray<T extends Foo>(foos: readonly T[]) {
return foos.reduce((acc, cur) => {
return {
...acc,
[cur.name]: cur
}
}, {} as { [K in T["name"]]: Extract<T, { name: K }>});
}
行为符合您的预期:
const objectFoos = createObjectFromFooArray(myFoos);
console.log(objectFoos.hello);
console.log(objectFoos.aaa); // error!
好的,希望能有所帮助;祝你好运!