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

261 typescript

我已经定义了这样的界面:

interface IModal {
    content: string;
    form: string;
    href: string;
    $form: JQuery;
    $message: JQuery;
    $modal: JQuery;
    $submits: JQuery;
 }
Run Code Online (Sandbox Code Playgroud)

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

var modal: IModal;
Run Code Online (Sandbox Code Playgroud)

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

"cannot set property content of undefined"
Run Code Online (Sandbox Code Playgroud)

有人可以帮我弄这个吗?是否可以使用界面来描述我的模态对象,如果是这样我应该如何创建它?

Fen*_*ton 357

如果你在其他地方创建"模态"变量,并想告诉TypeScript它将全部完成,你将使用:

declare const modal: IModal;
Run Code Online (Sandbox Code Playgroud)

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

const modal: IModal = {
    content: '',
    form: '',
    href: '',
    $form: null,
    $message: null,
    $modal: null,
    $submits: null
};
Run Code Online (Sandbox Code Playgroud)

或者说谎,使用类型断言,但是你将失去类型安全性,因为你现在将在意外的地方得到未定义,并且可能在访问时出现运行时错误modal.content等等(合同说明的那些属性).

const modal = {} as IModal;
Run Code Online (Sandbox Code Playgroud)

示例类

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

const modal = new Modal();
Run Code Online (Sandbox Code Playgroud)

您可能会认为"嘿,这真的是界面的重复" - 而且你是对的.如果Modal类是IModal接口的唯一实现,您可能想要完全删除该接口并使用...

const modal: Modal = new Modal();
Run Code Online (Sandbox Code Playgroud)

而不是

const modal: IModal = new Modal();
Run Code Online (Sandbox Code Playgroud)

  • `var modal = <IModal> {};`这就是我要找的东西;-)谢谢! (17认同)
  • 仅供参考,最好使用 `{} 作为 IModal` 而不是 `&lt;IModal&gt;{}`。它消除了在 JSX 中使用 `&lt;foo&gt;` 样式断言时语言语法中的歧义。[阅读更多](https://basarat.gitbooks.io/typescript/docs/types/type-assertion.html)。当然,使用 `let` 或 `const` 代替 `var`。 (10认同)
  • 谢谢。我希望最初不必定义所有模态内容。如果我将 Modal 定义为具有属性的类而不是接口,然后使用 new 和构造函数来设置所有初始值,会更容易吗? (2认同)
  • 我添加了一个示例和有关该接口的注释。 (2认同)

小智 172

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

var modal = <IModal>{};
Run Code Online (Sandbox Code Playgroud)

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

class TestClass {
    a: number;
    b: string;
    c: boolean;
}
Run Code Online (Sandbox Code Playgroud)

汇编成

var TestClass = (function () {
    function TestClass() {
    }
    return TestClass;
})();
Run Code Online (Sandbox Code Playgroud)

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


geg*_*geg 42

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

let a = {} as MyInterface;
Run Code Online (Sandbox Code Playgroud)

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


Nav*_*lah 32

有 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' };  
Run Code Online (Sandbox Code Playgroud)


Urs*_*gor 20

我认为你基本上有五种不同的选择.根据您希望实现的目标,在其中进行选择可能很容易.

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

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

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

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

    foo(param: string): void {
    }
}
Run Code Online (Sandbox Code Playgroud)

即使其他方法提供了从界面创建对象的更简单方法,您应该考虑将界面分开,如果您将对象用于不同的事情,并且它不会导致界面过度隔离:

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

interface IModal extends IBehaviour{
    content: string;
    form: string;
    //...
}
Run Code Online (Sandbox Code Playgroud)

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

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

 var modal = <IModal>{};
Run Code Online (Sandbox Code Playgroud)

其次要完全实现界面的必修部分.无论您是在调用第三方JavaScript库,都会很有用,但我认为您应该创建一个类,就像之前一样:

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

    foo: (param: string): void => {
    }
};
Run Code Online (Sandbox Code Playgroud)

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

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

    }
};
Run Code Online (Sandbox Code Playgroud)

即使接口是可选的,总结我的答案,因为它们不会被转换为JavaScript代码,如果明智且一致地使用,TypeScript可以提供新的抽象级别.我想,只是因为你可以在大多数情况下从你自己的代码中解雇它们,你不应该这样做.


Kan*_*ger 16

你可以做

var modal = {} as IModal 
Run Code Online (Sandbox Code Playgroud)


rbe*_*nto 11

这是另一种方法:

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

const modal: IModal = {} as IModal;
Run Code Online (Sandbox Code Playgroud)

或者基于接口和合理的默认值的默认实例,如果有的话

const defaultModal: IModal = {
    content: "",
    form: "",
    href: "",
    $form: {} as JQuery,
    $message: {} as JQuery,
    $modal: {} as JQuery,
    $submits: {} as JQuery
};
Run Code Online (Sandbox Code Playgroud)

然后简单地通过覆盖一些属性来改变默认实例

const confirmationModal: IModal = {
    ...defaultModal,     // all properties/values from defaultModal
    form: "confirmForm"  // override form only
}
Run Code Online (Sandbox Code Playgroud)


小智 9

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

var modal: IModal;
Run Code Online (Sandbox Code Playgroud)

经过

let modal: IModal = {} as IModal;
Run Code Online (Sandbox Code Playgroud)

应该回答这个问题。


小智 8

由于我没有在顶部找到相同的答案,我的答案是不同的.我做:

modal: IModal = <IModal>{}
Run Code Online (Sandbox Code Playgroud)


Ste*_*aul 6

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

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

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

new class implements MyInterface {
  nameFirst = 'John';
  nameFamily = 'Smith';
}();
Run Code Online (Sandbox Code Playgroud)

选项 2:创建实用函数:

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

impl<MyInterface>({
  nameFirst: 'John';
  nameFamily: 'Smith';
})
Run Code Online (Sandbox Code Playgroud)


M K*_*aei 6

let myDto = { id: 1, name: 'john' } as MyDto;
Run Code Online (Sandbox Code Playgroud)