【问题标题】:Shortcut syntax to Class constructor from TypeScript interface从 TypeScript 接口到类构造函数的快捷语法
【发布时间】:2021-09-23 10:15:09
【问题描述】:

如果我有如下的 TypeScript 界面:

interface myInterface {
    prop1: string;
    prop2: string;
    prop3: number;
    prop4: boolean;
    ..
    ..
    ..
    prop30: string
}

我想创建一个实现myInterface 的类,我只知道这样做的详细方法,如下所示:

class MyClass implements myInterface {
    prop1;
    prop2;
    prop3;
    prop4;
    ..
    ..
    prop30;

    constructor(data: myInterface) {
        this.prop1 = data.prop1;
        this.prop2 = data.prop2;
        this.prop3 = data.prop3;
        this.prop4 = data.prop4;
        ..
        ..
        this.prop30 = data.prop30;
    }
}

有什么方法可以让这个语法更短,或者有更好的方法从接口实现这样的类吗?

【问题讨论】:

  • 这只是一个 DTO 吗?如果是这样,你真的需要一个类吗?
  • 正是@VLAZ 所说的-var x: myInterface = { prop1: "hello", prop2: "world", prop3: 77, ...} 是该接口的有效实例。您在这里不需要需要课程(以防万一您不知道)。
  • 我同意@VLAZ,它是一个 DTO,但我也想要一些方法来根据其他属性更改来更改某些属性值(例如 prop1 值在 props2 和 prop3 更改时更改)。希望这是有道理的。这是一个非常具体的问题。
  • 如果它有 any 逻辑,而不仅仅是属性,则它不是 DTO。

标签: typescript


【解决方案1】:

您可以使用Object.assign()data 参数的所有成员一次复制到this,但TypeScript 仍然要求您单独declare the fields

class MyClass implements MyInterface {
    prop1!: string;
    prop2!: string;
    prop3!: number;
    prop4!: boolean;
    /* ..
    ..
    ..*/
    prop30!: string;
    constructor(data: MyInterface) {
        Object.assign(this, data);
    }
}

所以这更好,但不是很好。

(另请注意,编译器无法验证属性是否已分配,因此您需要在字段声明中使用definite assignment assertion operator (!) 来抑制警告。)


如果您可以定义一个类工厂函数并使用它来生成一个超类,那么您可以省去这个麻烦。函数如下:

function AssignCtor<T extends object>() {
    return class {
        constructor(t: T) {
            Object.assign(this, t)
        }
    } as { new(t: T): T }
}

AssignCtor&lt;T&gt; 的返回值是asserted 一个带有construct signature 的类型,它接受一个T 类型的值并产生一个同样类型为T 的类实例。这就是你想用MyInterface 做的,所以让我们试试吧:

class MyClass extends AssignCtor<MyInterface>() implements MyInterface {

}

就是这样。让我们确保 MyClass 的行为符合您的预期:

function tryItOut(data: MyInterface) {
    const myClass = new MyClass(data);
    myClass.prop1.toUpperCase(); // okay    
}

看起来不错。值myClass 被视为具有MyInterface 的属性。

Playground link to code

【讨论】:

  • 谢谢@jcalz 我认为类工厂函数对我有用。一旦我实施它,我将接受它作为答案。
  • @jcalz,这太棒了!我注意到的一件事是构造函数允许未实现的参数进入类实例。有什么防止这种情况的提示吗?
  • @DannyBeyrer 如果您可以提供您正在谈论的内容的minimal reproducible example(例如使用 tsplay.dev 链接),那么可能吗?请注意,先前已回答问题的 cmets 不是回答后续问题的好地方;如果事实证明它不仅仅是一条线,那么您可能想发表自己的问题。
  • 谢谢@jcalz。我在这里发布了我自己的问题:stackoverflow.com/q/70703950/4747264
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-07-08
  • 1970-01-01
  • 2010-11-11
  • 1970-01-01
相关资源
最近更新 更多