444

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

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

我定义了一个这样的变量:

var modal: IModal;

但是,当我尝试设置 modal 的属性时,它会给我一条消息说

"cannot set property content of undefined"

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

4

15 回答 15

588

如果您在别处创建“模态”变量,并想告诉 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();
于 2012-10-30T15:52:59.560 回答
243

如果你想要一个接口的空对象,你可以这样做:

var modal = <IModal>{};

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

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

编译成

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

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

于 2014-06-16T19:37:54.633 回答
83

如果您使用 React,解析器将阻塞传统的强制转换语法,因此引入了替代方案以在.tsx文件中使用

let a = {} as MyInterface;

https://www.typescriptlang.org/docs/handbook/jsx.html

于 2016-06-14T03:32:38.133 回答
23

你可以做

var modal = {} as IModal 
于 2017-12-03T10:26:25.077 回答
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>{};

其次要充分实现你界面的必修部分。无论您是否调用 3rd 方 JavaScript 库,这都会很有用,但我认为您应该创建一个类,就像以前一样:

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

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

第三,您可以只创建界面的一部分并创建一个匿名对象,但这样您有责任履行合同。

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

    }
};

总结一下我的回答,即使接口是可选的,因为它们没有被转译成 JavaScript 代码,TypeScript 可以提供一个新的抽象级别,如果使用得当的话。我认为,仅仅因为您可以在大多数情况下从您自己的代码中忽略它们,您不应该这样做。

于 2015-12-13T17:59:23.680 回答
17

这是另一种方法:

您可以像这样简单地创建一个 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
}
于 2019-08-31T04:50:20.517 回答
14

因为我没有在顶部找到一个相同的答案,所以我的答案是不同的。我愿意:

modal: IModal = <IModal>{}
于 2018-01-23T09:23:38.077 回答
4

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

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

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

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

选项 2:创建效用函数:

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

impl<MyInterface>({
  nameFirst: 'John';
  nameFamily: 'Smith';
})
于 2019-11-05T20:25:06.033 回答
4

由于问题包括 TypeScript 的使用,因此替换

var modal: IModal;

经过

let modal: IModal = {} as IModal;

应该回答这个问题。

于 2021-03-18T12:47:49.393 回答
3

您可以使用 设置默认值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}
于 2020-06-19T00:11:30.200 回答
2

有 5 种方法可以使用该界面。

interface IStudent {
      Id: number;
      name: string;
    }
    
    
    Method 1. all fields must assign data.
     const  obj1: IStudent = { Id: 1, name: 'Naveed' };  
    
    Method 2. my favorite one
    const obj2 = { name: 'Naveed' } as IStudent ;
    
    Method 3.
    const obj3 = <IStudent >{name: 'Naveed'}; 
    
    Method 4. use partial interface if all fields not required.
    const  obj4: Partial<IStudent > = { name: 'Naveed' };  
    
    Method 5. use ? Mark with interface fields if all fields not required.
    const  obj5: IStudent = {  name: 'Naveed' };  
于 2021-12-02T20:15:16.243 回答
1

使用您的界面,您可以做到

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.
  }
}
于 2017-04-13T10:39:49.060 回答
0

这是我经常使用的另一种解决方案。但是我不确定是否是好的做法,如果不是,请在下面评论。

/// 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);

谢谢 :)

于 2020-10-26T13:40:22.787 回答
0

您实际上不需要类来创建对象。你可以直接这样做:

interface IModal {
    content: string;
    form: string;
}

onButtonSaveClick() {
    let myModalClass: IModal = {
        content: 'foo content',
        form: 'foo form'
    }
}
于 2021-03-15T16:32:08.033 回答
-1
let deletedQuestionsDto = { examId: this.examId, questionId: q.id } as DeletedQuestionsDto;
于 2021-12-07T09:15:00.410 回答