将对象数组映射到打字稿中具有不同对象的另一个数组

rst*_*rst 5 typescript

如果我有类似的东西

array1: string[] = ['foo', 'bar'];
Run Code Online (Sandbox Code Playgroud)

和一个界面

export interface MyObject { name: string; }
Run Code Online (Sandbox Code Playgroud)

如何将 array1 映射到另一个 MyObject 类型的数组?

array2 : MyObject[];
array2 = array1.map(s => ...);
Run Code Online (Sandbox Code Playgroud)

我想过类似的事情

array2 = array1.map<MyObject>(s => new MyObject(...));
Run Code Online (Sandbox Code Playgroud)

jca*_*alz 15

这通常是我进入关于 TypeScript 中类型和值之间差异的长篇演讲的地方,但在这里我会尽量简短:因为MyObject只知道是类型而不是构造函数,你不能调用new MyObject(). 相反,如果您想创建一个 type 值MyObject,您可以只使用正确形状的普通旧对象,例如通过对象文字表示法

const myObject: MyObject = {name: "Alice"}; // no error
Run Code Online (Sandbox Code Playgroud)

所以你的map功能可以如下:

const array2: MyObject[] = array1.map(s => ({name: s})); // no error
Run Code Online (Sandbox Code Playgroud)

很简单吧?

呃,好吧,请注意在上面的评论中,括号{name: s}必要的,因为无论好坏,JavaScript 解析器将表单的箭头函数解释(x => {...})为具有块体,其中大括号内的内容是语句。当您将其解释name: s语句时,它意味着它name是一个标签,并且s只是一个省略可选分号的字符串表达式语句。解释为函数体,只计算而不返回定义的值(它是),这就是为什么如果省略括号会出现以下奇怪的错误:{name: s}svoid,本质上与undefined

let array2: MyObject[] = array1.map(s => { name: s }); // error!
// Type 'void[]' is not assignable to type 'MyObject[]'.
// at runtime, array2 will be [undefined, undefined] which is not what you wanted 
Run Code Online (Sandbox Code Playgroud)

JavaScript 解析这种方式有点棘手。添加括号来s => (...)修复它。现在箭头后面的东西只能解释为一个简洁的主体……也就是一个单一的表达。解释({name: s})为表达式会产生我们想要的对象字面量。

是的,我避免写一本关于类型和值的书,结果以某种方式写了一本关于表达式和语句的不同的书。那好吧。

希望能帮到你。祝你好运!


Art*_*yan 10

你不能MyObject作为构造函数调用,因为它是interface而不是class。因此,这里的一个选项您可以将array1属性映射为MyObject属性,然后将类型更改为MyObject[]数组as

const array1: string[] = ['foo', 'bar'];

export interface MyObject { name: string; }

let array2 : MyObject[];

array2 = array1.map(v => { return {name: v}; }) as MyObject[];
Run Code Online (Sandbox Code Playgroud)

或者另一种选择,您还可以创建MyObject将实现IMyObject接口的类,并且可以调用构造函数。这是一个例子

const array1: string[] = ['foo', 'bar'];

export interface IMyObject { name: string; }

class MyObject implements IMyObject {
  name: string;

  constructor(name: string) {
    this.name = name;
  }
}

let array2 : IMyObject[];

array2 = array1.map(v => new MyObject(v)) as IMyObject[];
Run Code Online (Sandbox Code Playgroud)