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

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

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"

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

597672 次浏览

如果你在其他地方创建了“modal”变量,并想告诉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();

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

var modal = <IModal>{};

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

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

编译成

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

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

我认为你基本上有五种不同的选择来这样做。根据你想要达到的目标,从中选择可能很容易。

在大多数情况下使用一个类并实例化它是最好的方法,因为你正在使用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在那里提供了一个新的抽象级别,如果使用得当和一致的话。我认为,只是因为在大多数情况下你可以在自己的代码中忽略它们,你不应该这样做。

如果你正在使用React,解析器会阻塞在传统的强制转换语法上,所以引入了一个替代方案用于.tsx文件

let a = {} as MyInterface;

https://www.typescriptlang.org/docs/handbook/jsx.html < a href = " https://www.typescriptlang.org/docs/handbook/jsx.html " > < / >

使用你的界面就可以做到

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

你可以这样做

var modal = {} as IModal

因为我还没有在顶部找到一个相等的答案,我的答案是不同的。 我:< / p >

modal: IModal = <IModal>{}

下面是另一种方法:

你可以像这样简单地创建一个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:实例化一个实现接口的匿名类:

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

选项2:创建一个实用函数:

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


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

可以使用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}

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

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

谢谢:)

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

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


onButtonSaveClick() {
let myModalClass: IModal = {
content: 'foo content',
form: 'foo form'
}
}

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

var modal: IModal;

通过

let modal: IModal = {} as IModal;

应该回答这个问题。

该界面有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' };
let deletedQuestionsDto = { examId: this.examId, questionId: q.id } as DeletedQuestionsDto;