我定义了这样的接口:

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"


是否可以使用接口来描述我的模态对象?我应该创建它吗?

#1 楼

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

declare const modal: IModal;


如果要创建变量它实际上将是TypeScript中IModal的一个实例,您将需要对其进行完全定义。因为现在访问modal.content等时(在合同规定的属性中),在意外的地方(可能会出现运行时错误)使您变得不确定,

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




const modal = {} as IModal;


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

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

const modal = new Modal();


而不是

const modal: Modal = new Modal();


评论


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

–user1679941
2012年10月30日在16:24



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

– Fenton
2012年10月30日16:25

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

– Fenton
2012年10月30日在16:37

var modal = {};这就是我想要的;-)谢谢!

–传奇
17 Mar 4 '17 at 21:02



仅供参考,最好将{}用作IModal,而不是 {}。在JSX中使用样式断言时,它消除了语言语法上的歧义。阅读更多。当然,请使用let或const代替var。

– Alex Klaus
18-10-2在7:55

#2 楼

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

var modal = <IModal>{};


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

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


编译成

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


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

评论


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

–晴天
2015年8月30日12:22



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

–帕迪普·in那教
16年1月7日在6:26

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

–拉胡尔(Rahul Sonwanshi)
20-2-27在18:36

#3 楼

如果您使用的是React,则解析器将阻塞传统的强制转换语法,因此引入了一种替代方法,供.tsx文件使用。

.org / docs / handbook / jsx.html

#4 楼

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

在大多数情况下,使用类并实例化它的最佳方法,因为您正在使用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 => {
    }
};


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

#5 楼

您可以

var modal = {} as IModal 


#6 楼

由于我没有在顶部找到相等的答案,而且答案也有所不同。
我这样做:

modal: IModal = <IModal>{}


#7 楼

这是另一种方法:

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

const modal: IModal = {} as IModal;


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

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


然后只需覆盖某些属性即可更改默认实例的变体


#8 楼

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

对于那些对其他健壮而紧凑的解决方案感兴趣的人:

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

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


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

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

impl<MyInterface>({
  nameFirst: 'John';
  nameFamily: 'Smith';
})


#9 楼

您可以使用Class设置默认值。

不带类构造函数:

interface IModal {
  content: string;
  form: string;
  href: string;
  isPopup: boolean;
};

class Modal implements IModal {
  content = "";
  form = "";
  href: string;  // will not be added to object
  isPopup = true;
}

const myModal = new Modal();
console.log(myModal); // output: {content: "", form: "", isPopup: true}


带类构造函数

interface IModal {
  content: string;
  form: string;
  href: string;
  isPopup: boolean;
}

class Modal implements IModal {
  constructor() {
    this.content = "";
    this.form = "";
    this.isPopup = true;
  }

  content: string;

  form: string;

  href: string; // not part of constructor so will not be added to object

  isPopup: boolean;
}

const myModal = new Modal();
console.log(myModal); // output: {content: "", form: "", isPopup: true}


#10 楼

您可以使用界面

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.
  }
}


#11 楼

这是我经常使用的另一种解决方案。但是,我不确定这是否是一种好的做法,如果没有,请在下面评论。
/// Interface
export default interface BookInterface {
  title: string,
  author: string,
  id: any
}

/// Creating Class
export class BookClass implements BookInterface {
  title: string;
  author: string;
  id: any;

  constructor(title: string, author: string, id: any) {
    this.title = title;
    this.author = author;
    this.id = id;
  }
}

/// How to use it
let book: BookInterface = new BookClass(title, author, id);

谢谢:)

评论


基本上是一种不好的做法,因为接口仅在编译时使用,并导致精简的js文件缩小,而类将被编译为js类(函数),这会增加代码和复杂性

–efkah
20 Nov 11'在11:05