如何基于TypeScript中的接口文件定义创建对象?


313

我已经定义了这样的接口:

interface IModal {
    content: string;
    form: string;
    href: string;
    $form: JQuery;
    $message: JQuery;
    $modal: JQuery;
    $submits: JQuery;
 }

我定义一个这样的变量:

var modal: IModal;

但是,当我尝试设置模式属性时,会给我一条消息,内容是

"cannot set property content of undefined"

使用接口描述我的模态对象可以吗?如果是,我应该如何创建它?

Answers:


426

如果要在其他地方创建“模式”变量,并想告诉TypeScript全部完成,则可以使用:

declare const modal: IModal;

如果要创建一个实际上将是TypeScript中IModal实例的变量,则需要完全定义它。

const modal: IModal = {
    content: '',
    form: '',
    href: '',
    $form: null,
    $message: null,
    $modal: null,
    $submits: null
};

使用类型断言还是说谎,但是您将失去类型安全性,因为现在访问时,在意外的地方(可能会出现运行时错误)modal.content(合同约定的属性在那里),您将无法定义它。

const modal = {} as IModal;

示例类

class Modal implements IModal {
    content: string;
    form: string;
    href: string;
    $form: JQuery;
    $message: JQuery;
    $modal: JQuery;
    $submits: JQuery;
}

const modal = new Modal();

您可能会认为“嘿,那实际上是界面的重复”-您是正确的。如果Modal类是IModal接口的唯一实现,则您可能希望完全删除该接口并使用...

const modal: Modal = new Modal();

而不是

const modal: IModal = new Modal();

2
谢谢。我希望摆脱最初定义所有模态内容的麻烦。如果我将Modal定义为具有属性的类,然后使用new和构造函数来设置所有初始值,而不是使用接口,会更容易吗?

1
是的-您可以定义一个类,然后只需要在需要时创建新实例即可。您需要一个例子吗?
Fenton 2012年

2
我添加了一个示例和有关该接口的注释。
Fenton 2012年

21
var modal = <IModal>{};这就是我想要的;-)谢谢!
传说

5
仅供参考,最好使用{} as IModal而不是<IModal>{}<foo>在JSX中使用样式断言时,它消除了语言语法上的歧义。阅读更多。当然,请使用letconst代替var
亚历克斯·克劳斯

191

如果您想要接口的空对象,则可以执行以下操作:

var modal = <IModal>{};

使用接口代替类来构造数据的优点是,如果类上没有任何方法,它将在已编译的JS中显示为空方法。例:

class TestClass {
    a: number;
    b: string;
    c: boolean;
}

编译成

var TestClass = (function () {
    function TestClass() {
    }
    return TestClass;
})();

没有价值。另一方面,接口根本不显示在JS中,同时仍然提供数据结构化和类型检查的好处。


1
`添加到上述注释中。要调用函数“ updateModal(IModal modalInstance){}”,您可以创建接口“ IModal”的内联实例,如下所示://此处提供一些代码,可访问updateModal函数和IModal:updateModal(<IModal> {//此行创建一个实例内容:”,形式:”,href:”,$ form:null,$ message:null,$ modal:null,$ submits:null});//完成您的代码`
2015年

通过使用,var modal= <abc>{}我们只为空对象分配了abc类型的模式,但是在哪里声明了模式的类型?我正在使用typescript6。
Pardeep Jain

这对我不起作用,我必须按照接受的答案中所述初始化整个对象。
Rahul Sonwanshi


22

我认为您基本上有五个不同的选择。根据您要实现的目标,在它们之间进行选择可能很容易。

在大多数情况下,使用类并实例化它的最佳方法,因为您正在使用TypeScript进行类型检查。

interface IModal {
    content: string;
    form: string;
    //...

    //Extra
    foo: (bar: string): void;
}

class Modal implements IModal {
    content: string;
    form: string;

    foo(param: string): void {
    }
}

即使其他方法提供了从接口创建对象的更简便方法,您也应该考虑将接口分开,如果您将对象用于其他事项,并且不会导致接口过度分离:

interface IBehaviour {
    //Extra
    foo(param: string): void;
}

interface IModal extends IBehaviour{
    content: string;
    form: string;
    //...
}

另一方面,例如在对代码进行单元测试期间(如果您可能不经常应用关注点分离),则可能会为了提高生产率而接受这些缺点。您可以应用其他方法来为大型第三方* .d.ts接口创建模拟。总是为每个巨大的接口实现完全匿名的对象可能会很痛苦。

在此路径上,您的第一个选择是创建一个空对象

 var modal = <IModal>{};

其次要充分实现界面的强制性部分。是否调用第三方JavaScript库可能很有用,但是我认为您应该像以前那样创建一个类:

var modal: IModal = {
    content: '',
    form: '',
    //...

    foo: (param: string): void => {
    }
};

第三,您可以只创建一部分接口并创建一个匿名对象,但是通过这种方式您有责任履行合同

var modal: IModal = <any>{
    foo: (param: string): void => {

    }
};

即使接口是可选的,我也总结了我的答案,因为它们没有被转换为JavaScript代码,因此TypeScript可以提供一个新的抽象级别(如果明智且一致地使用)。我认为,只是因为您可以在大多数情况下从自己的代码中删除它们,所以您不应该这样做。



12

因为我没有在顶部找到相等的答案,所以我的答案有所不同。我做:

modal: IModal = <IModal>{}

2

使用界面,您可以执行

class Modal() {
  constructor(public iModal: IModal) {
   //You now have access to all your interface variables using this.iModal object,
   //you don't need to define the properties at all, constructor does it for you.
  }
}

2

这是另一种方法:

您可以像这样简单地创建一个ESLint友好对象

const modal: IModal = {} as IModal;

或基于接口和合理默认值的默认实例(如果有)

const defaultModal: IModal = {
    content: "",
    form: "",
    href: "",
    $form: {} as JQuery,
    $message: {} as JQuery,
    $modal: {} as JQuery,
    $submits: {} as JQuery
};

然后只需覆盖一些属性即可更改默认实例

const confirmationModal: IModal = {
    ...defaultModal,     // all properties/values from defaultModal
    form: "confirmForm"  // override form only
}

1

迄今为止发布的许多解决方案都使用类型声明,因此 ,如果在实现中省略了所需的接口属性,则不会引发编译错误。

对于那些对其他强大而紧凑的解决方案感兴趣的人

选项1:实例化实现该接口的匿名类:

new class implements MyInterface {
  nameFirst = 'John';
  nameFamily = 'Smith';
}();

选项2:创建实用程序功能:

export function impl<I>(i: I) { return i; }

impl<MyInterface>({
  nameFirst: 'John';
  nameFamily: 'Smith';
})
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.