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

use*_*143 12 constructor copy-constructor typescript

我在 type script 上有一堂课:

export class Child {
  name:string;
  age:number;
}
Run Code Online (Sandbox Code Playgroud)

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

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

myFirebaseService.getChild(id).then(function(child){
  var currentChild = new Child(child);
}) 
Run Code Online (Sandbox Code Playgroud)

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

currentChild = {"name":"ben"}
Run Code Online (Sandbox Code Playgroud)

因为“颜色”不是“孩子”的领域。

我试过这个:

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

  constructor(tempChild:Child = null) {
    if (tempChild){
      for (var prop in tempChild) {
        this[prop] = tempChild[prop];
      }
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

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

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

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

  constructor(tempChild:Child = null) {
    if (tempChild){
      this.nam  = tempChild.name;
      this.age =tempChild.ageÏ;
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

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

ego*_*xyz 11

我们想要的是:

  • 一次声明类字段
  • 我们班有方法

解决方案:

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());
Run Code Online (Sandbox Code Playgroud)

Animal - 根类

Dog - 嵌套类

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


Bal*_*des 8

在我看来,从任意对象构建类实例的最干净的方法是使用解构。您仍然可以对所有字段进行分配,但是您可以(非常干净地)控制该字段不存在时会发生的情况,以及将分配给类字段的字段:

export class Child {
  name:string
  age:number

  constructor({name = 'default name', age = 0} = {}) {
    this.name = name
    this.age = age
  }
}
Run Code Online (Sandbox Code Playgroud)

现在,这可以让您从Objects 或anys 或任何部分对象文字创建实例,但是当使用文字时,它不会让您添加额外的东西,这似乎是您所需要的:

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
Run Code Online (Sandbox Code Playgroud)

生成的 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;
});
Run Code Online (Sandbox Code Playgroud)

尝试在操场上看看由此生成了什么!


Nit*_*mer 2

这里没有太多选择,因为您在构造函数之前在类中进行的成员定义不会被转换为 javascript,编译器会将它们排除在外:

class Child {
    name: string;
    age: number;

    constructor() {
        this.name = "name";
    }
}
Run Code Online (Sandbox Code Playgroud)

编译成:

var Child = (function () {
    function Child() {
        this.name = "name";
    }
    return Child;
}());
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,该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];
                }
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

这使用起来不太舒服,所以你可以使用装饰器。
例如:

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];
                }
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

操场上的代码

它没有经过测试,所以我不确定它是否有效,但如果您决定这样做,那么它就是您所需要的大部分内容。