打字稿:如何将对象转换或分配给属性较少的类型? (从大到小)

时间:2019-08-19 11:23:56

标签: typescript

我有三个对象(类),它们如下:

class A {

  public value1: string;
  public value2: string;
  public value3: string;
  public value4: string;
  public value5: string;

}

class B {

  public value1: string;
  public value2: string;

}

class C {

  public value3: string;
  public value4: string;
  public value5: string;

}

现在我有一个像这样的JSON:

{
  "value1": "ONE",
  "value2": "TWO",
  "value3": "THREE",
  "value4": "FOUR",
  "value5": "FIVE"
}

我想知道是否有任何干净的方法将类A转换为类B和类C

我尝试了这种方法,但是在map之后,类B具有A中的所有5个属性,而不是B上定义的2个属性。

class B {

  public value1: string;
  public value2: string;

  constructor(item: A) {
    Object.assign(this, item);
  }

}


let arr1: A[{"value1":"ONE","value2":"TWO","value3":"THREE","value4":"FOUR","value5":"FIVE"}];
let arr2 = arr1.map(item => new B(item));
Result: B -> {"value1":"ONE","value2":"TWO","value3":"THREE","value4":"FOUR","value5":"FIVE"}]
instead of 
B -> {"value1":"ONE","value2":"TWO"}]

2 个答案:

答案 0 :(得分:1)

您要求打字稿修改值
Typescript不会运行您的代码,只会编译并检查类型安全性

您可以做的是:为B类定义空道具,然后检查键

class A {
  public value1: string
  public value2: string
  public value3: string
  public value4: string
  public value5: string
}
class B {
  public value1: string = undefined // <-- define
  public value2: string = undefined // <-- define
  constructor (item: A) {
    const keys = Object.keys(item) // get items keys
    const thisKeys = Object.keys(this) // get this class keys
    const limitedItem = keys.reduce((newObj, key) => { // combine same keys
      if (thisKeys.includes(key)) {
        newObj[key] = item[key]
      }
      return newObj
    }, {})
    Object.assign(this, limitedItem) // asign to this class
  }
}

const arr1 = [{ value1: '1', value2: '2', value3: '3', value4: '4', value5: '5' }]
let arr2 = arr1.map(item => new B(item))
console.log('arr2', arr2)

// arr2 [ B { value1: '1', value2: '2' } ]

答案 1 :(得分:1)

来自TypeScript Deep Dive

  

类型断言与强制转换

     

之所以不称为“类型转换”的原因是,转换通常意味着某种运行时支持。但是,类型断言纯粹是一种编译时结构,是您向编译器提供有关如何分析代码的提示的一种方式。

类型断言告诉Typescript编译器您已经知道某个值可以安全地视为另一种类型,即使无法通过静态分析对其进行验证也是如此。

类型断言示例

class A {
    constructor(public val1: string, public val2: string, public val3: string,
        public val4: string, public val5: string) {}
}

class B {
    constructor(public num1: number, public num2: number) {}
}

由于类型AB不重叠,如果您尝试将A的实例分配给B,则Typescript编译器将发出警告。

let a = new A('a', 'b', 'c', 'd', 'e');
let b: B = a;  // Error: Type 'A' is missing the following properties from type 'B': num1, num2

使用类型断言,可以告诉编译器忽略不匹配的类型,在这种情况下,这是个坏主意。

let a = new A('a', 'b', 'c', 'd', 'e');
let b: B = <any> a;
let b2: B = a as any;

您要问的是,如何在复制具有比目标类更多属性的类的实例时限制分配的属性。在您的示例中,一种简单的方法是为staticB创建C的工厂函数(即专门的构造函数),它们接受A的实例,如下所示。

使用静态工厂功能的示例

class A {
    constructor(public val1: string, public val2: string, public val3: string,
        public val4: string, public val5: string) {}
}

class B {
    constructor(public val1: string, public val2: string) {}

    static constructFromA(a: A): B {
        return new B(a.val1, a.val2);
    } 
}

class C {
    constructor(public val3: string, public val4: string, public val5: string) {}

    static constructFromA(a: A): C {
        return new C(a.val3, a.val4, a.val5);
    } 
}


let a = new A('a', 'b', 'c', 'd', 'e');
let b = B.constructFromA(a);
let c = C.constructFromA(a);

console.log(JSON.stringify(b, null, 2));
console.log(JSON.stringify(c, null, 2));

输出

// New B from A
{
  "val1": "a",
  "val2": "b"
}

// New C from A
{
  "val3": "c",
  "val4": "d",
  "val5": "e"
}
相关问题