打字稿:来自对象的新实例

时间:2019-04-01 16:50:45

标签: typescript constructor

有没有办法用Typescript实现类似的事情?

class Person {
   public name: string;

   constructor(data:any) {
      this = Object.assign(this, data);
   }
}

const p = new Person({name: "Daniel", "age": 30, "gender": "M"});
console.log(p.name) //Daniel
console.log(p.age)  //undefined
console.log(p.gender) //undefined

1 个答案:

答案 0 :(得分:0)

取决于您的目标。您可以使用Partial

禁止将此类对象文字传递给构造函数
class Person {
    public name!: string;

    constructor(data:Partial<Person>) {
        Object.assign(this, data);
    }
}

const p = new Person({name: "Daniel", "age": 30, "gender": "M"}); // error on age and gender

这使用打字稿的多余属性检查来触发这些字段的错误(尽管您应该阅读多余属性检查的更多信息,因为它们仅在将对象文字直接分配给特定类型的参数或变量时才触发)。长话短说,您可能仍会在this上留下更多内容。

另一个选择是给我们一个自定义assign函数,该函数仅分配非函数字段。 Typescript不允许我们在运行时访问类型信息,因此最简单的解决方案是使用映射类型,这将迫使我们创建与原始类型具有相同字段的对象:

type NonFunctionFields<T> = {
    [P in keyof T]-?: T[P] extends Function ? never : P
}[keyof T];

function assignFactory<T>(fields: Record<NonFunctionFields<T>, 1>) {
    return function (target: T, data: Partial<T>) {
        for (let key of Object.keys(fields) as Array<keyof T>) {
            if (key in data) {
                target[key] = data[key]!
            }
        }
    }
}

class Person {
    public name!: string;
    static personAssign = assignFactory<Person>({
        name: 1
    });
    constructor(data: Partial<Person>) {
        Person.personAssign(this, data);
    }
}
const data = { name: "Daniel", "age": 30, "gender": "M" };
const p = new Person(data);
console.log(p.name) //Daniel
console.log(p.age)  //undefined
console.log(p.gender) //undefined