TypeScript - 传递给构造函数的整个对象

时间:2016-11-10 06:45:59

标签: typescript constructor copy-constructor

我在类型脚本上有一个类:

export class Child {
  name:string;
  age:number;
}

我想强制类实例只有类声明所具有的属性。

例如,如果我从firebase获取一个对象:

myFirebaseService.getChild(id).then(function(child){
  var currentChild = new Child(child);
}) 

所以当对象是:{name:“ben”,color:“db”}时,我希望结果为:

currentChild = {"name":"ben"}

Becouse“color”不是“child”的领域。

我试过了:

export class Child {
  name:string;
  age:number;

  constructor(tempChild:Child = null) {
    if (tempChild){
      for (var prop in tempChild) {
        this[prop] = tempChild[prop];
      }
    }
  }
}

但它没有帮助。 “currentChild”获取所有字段并将它们附加到类实例。

(当然,我可以使用以下代码:

export class Child {
  name:string;
  age:number;

  constructor(tempChild:Child = null) {
    if (tempChild){
      this.nam  = tempChild.name;
      this.age =tempChild.ageÏ;
    }
  }
}

,但我的真相课有很多字段,我想要短代码

3 个答案:

答案 0 :(得分:2)

你在这里没有多少选择,因为你在构造函数之前在类中创建的成员定义没有被翻译成javascript,编译器将它们排除在外:

class Child {
    name: string;
    age: number;

    constructor() {
        this.name = "name";
    }
}

编译成:

var Child = (function () {
    function Child() {
        this.name = "name";
    }
    return Child;
}());

正如您所看到的,name成员是唯一存在的成员,甚至仅在分配时使用。

因为您需要在运行时使用成员的名称,所以您需要将它们放在一边,例如在数组中:

class Child {
    private static MEMBERS = ["name", "age"];

    name: string;
    age: number;

    constructor(tempChild: Child = null) {
        if (tempChild) {
            for (var prop in tempChild) {
                if (Child.MEMBERS.indexOf(props) >= 0) {
                    this[prop] = tempChild[prop];
                }
            }
        }
    }
}

使用它并不是很舒服,所以你可以使用装饰器 例如:

function member(cls: any, name: string) {
    if (!cls.constructor.MEMBERS) {
        cls.constructor.MEMBERS = [];
    }

    cls.constructor.MEMBERS.push(name);
}

function isMember(cls: any, name: string): boolean {
    return cls.MEMBERS[name] != null;
}

class Child {
    @member
    name: string;

    @member
    age: number;

    constructor(tempChild: Child = null) {
        if (tempChild) {
            for (var prop in tempChild) {
                if (isMember(Child, prop)) {
                    this[prop] = tempChild[prop];
                }
            }
        }
    }
}

code in playground

它没有经过测试,所以我不确定它是否正常工作,但如果你决定采用这种方式,那么它就是你需要的大部分内容。

答案 1 :(得分:1)

我们想要的:

  • 一次声明类字段
  • 在我们的课堂上有方法

解决方案:

class Animal {
  name: string = 'default value';
  group: string = 'default value';

  constructor(data: Partial<Animal> = {}) { Object.assign(this, data) }

  echo() {
    return `My name is ${this.name}, I'm from: ${this.group}`;
  }
}

class Dog extends Animal {
  echo() {
    return super.echo() + ' from Dog class';
  }
}

const dog = new Dog({name: 'Teddy'});
console.log(dog.echo());

Animal-根类

Dog-嵌套类

所有作品都没有打字稿错误

答案 2 :(得分:0)

在我看来,从任意对象构建类实例的最简洁方法是使用解构。您仍然可以为所有字段分配,但如果字段不存在,您可以(非常干净地)控制会发生什么,以及您将为类字段分配哪些字段:

export class Child {
  name:string
  age:number

  constructor({name = 'default name', age = 0} = {}) {
    this.name = name
    this.age = age
  }
}

现在,您可以从Objectany s或任何部分对象文字创建实例,但在使用文字时,它不会让您添加额外的内容,这似乎是你需要什么:

const c0 = new Child({} as any /* as Object works as well */)
const c1 = new Child({}) // Literal, will be using defaults
const c2 = new Child() // No argument, using defaults only
const c3 = new Child({ name: 'a', age: 1 })
const c4 = new Child({ name: 'b', foo: 'bar'}) // error with foo

生成的js将检查您手动检查的所有内容:

define(["require", "exports"], function (require, exports) {
    "use strict";
    var Child = (function () {
        function Child(_a) {
            var _b = _a === void 0 ? {} : _a, _c = _b.name, name = _c === void 0 ? 'default name' : _c, _d = _b.age, age = _d === void 0 ? 0 : _d;
            this.name = name;
            this.age = age;
        }
        return Child;
    }());
    exports.Child = Child;
});

尝试在playground中查看从中生成的内容!