Typescript 将一种类型的数组转换为该类型的映射对象

Typescript 将一种类型的数组转换为该类型的映射对象,typescript,Typescript,我想做这样的事情: type Foo = { name: string; value: any; } const myFoos: Foo[] = [ { name: "hello", value: 1, }, { name: "world", value: "bar" } ]; function createObjectFromFooArray(foos: Foo[]) : Re

我想做这样的事情:

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={
名称:字符串;
价值:任何;
}
const myFoos:Foo[]=[
{
姓名:“你好”,
价值:1,
},
{
名称:“世界”,
值:“bar”
}
];
函数createObjectFromFooArray(foos:Foo[]):记录{//需要更改返回类型
返回foos.reduce((acc,cur)=>{
返回{
…acc,
[当前名称]:当前
}
}, {});
}
const objectFoos=createObjectFromFooArray(myFoos);
log(objectFoos.hello);
log(objectFoos.aaa)//应该出错

也就是说,给定一个
Foo
s数组,我希望创建一个
Foo
s的映射对象,并且我希望该对象只包含作为原始
Foo
数组的
name
属性的索引。我该怎么做

这里有几个问题。一个是您必须抵制将
myFoos
注释为
Foo[]
,因为这会使编译器将
name
属性扩展为
string
,而您需要跟踪类似的
“hello”
“world”
。相反,您应该使用类似于a的东西来保持
myFoos
尽可能窄的键入:

const myFoos = [
  {
    name: "hello",
    value: 1,
  },
  {
    name: "world",
    value: "bar"
  }
] as const;
然后您可以让
createObjectFromFooArray
foos
元素的类型
T
中成为泛型,其中
T
被约束为
Foo
,但可以更具体。返回类型可以是一种条件映射类型,它对键的
T
name
属性进行迭代,并为每个属性值提取相应的
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!