如何根据 TypeScript 中的接口文件定义创建对象?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/13142635/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How can I create an object based on an interface file definition in TypeScript?
提问by Fenton
I have defined an interface like this:
我定义了一个这样的接口:
interface IModal {
content: string;
form: string;
href: string;
$form: JQuery;
$message: JQuery;
$modal: JQuery;
$submits: JQuery;
}
I define a variable like this:
我定义了一个这样的变量:
var modal: IModal;
However, when I try to set the property of modal it gives me a message saying that
但是,当我尝试设置 modal 的属性时,它会给我一条消息说
"cannot set property content of undefined"
Is it okay to use an interface to describe my modal object and if so how should I create it?
是否可以使用接口来描述我的模态对象,如果可以,我应该如何创建它?
回答by Fenton
If you are creating the "modal" variable elsewhere, and want to tell TypeScript it will all be done, you would use:
如果你在别处创建“modal”变量,并想告诉 TypeScript 一切都会完成,你可以使用:
declare const modal: IModal;
If you want to create a variable that will actually be an instance of IModal in TypeScript you will need to define it fully.
如果你想创建一个变量,它实际上是 TypeScript 中 IModal 的一个实例,你需要完全定义它。
const modal: IModal = {
content: '',
form: '',
href: '',
$form: null,
$message: null,
$modal: null,
$submits: null
};
Or lie, with a type assertion, but you'll lost type safety as you will now get undefined in unexpected places, and possibly runtime errors, when accessing modal.content
and so on (properties that the contract says will be there).
或者说谎,使用类型断言,但是您将失去类型安全性,因为您现在将在意外的地方未定义,并且可能会在访问时出现运行时错误modal.content
等(合同所说的属性将在那里)。
const modal = {} as IModal;
Example Class
示例类
class Modal implements IModal {
content: string;
form: string;
href: string;
$form: JQuery;
$message: JQuery;
$modal: JQuery;
$submits: JQuery;
}
const modal = new Modal();
You may think "hey that's really a duplication of the interface" - and you are correct. If the Modal class is the only implementation of the IModal interface you may want to delete the interface altogether and use...
您可能会想“嘿,这确实是界面的重复”-您是对的。如果 Modal 类是 IModal 接口的唯一实现,您可能希望完全删除该接口并使用...
const modal: Modal = new Modal();
Rather than
而不是
const modal: IModal = new Modal();
回答by user3180970
If you want an empty object of an interface, you can do just:
如果你想要一个接口的空对象,你可以这样做:
var modal = <IModal>{};
The advantage of using interfaces in lieu of classes for structuring data is that if you don't have any methods on the class, it will show in compiled JS as an empty method. Example:
使用接口代替类来构造数据的优点是,如果类上没有任何方法,它将在编译后的 JS 中显示为空方法。例子:
class TestClass {
a: number;
b: string;
c: boolean;
}
compiles into
编译成
var TestClass = (function () {
function TestClass() {
}
return TestClass;
})();
which carries no value. Interfaces, on the other hand, don't show up in JS at all while still providing the benefits of data structuring and type checking.
没有任何价值。另一方面,接口根本不会出现在 JS 中,同时仍然提供数据结构和类型检查的好处。
回答by geg
If you are using React, the parser will choke on the traditional cast syntax so an alternative was introduced for use in .tsxfiles
如果您使用 React,解析器将阻塞传统的强制转换语法,因此引入了一个替代方案以用于.tsx文件
let a = {} as MyInterface;
回答by Ursegor
I think you have basically five different optionsto do so. Choosing among them could be easy depending on the goal you would like to achieve.
我认为您基本上有五种不同的选择可以这样做。根据您想要实现的目标,在其中进行选择可能很容易。
The best way in most of the cases to use a class and instantiate it, because you are using TypeScript to apply type checking.
在大多数情况下使用类并实例化它的最佳方法,因为您正在使用 TypeScript 来应用类型检查。
interface IModal {
content: string;
form: string;
//...
//Extra
foo: (bar: string): void;
}
class Modal implements IModal {
content: string;
form: string;
foo(param: string): void {
}
}
Even if other methods are offering easier ways to create an object from an interface you should consider splitting your interfaceapart, if you are using your object for different matters, and it does not cause interface over-segregation:
即使其他方法提供了从接口创建对象的更简单方法,如果您将对象用于不同的事务,并且不会导致接口过度隔离,您也应该考虑将接口分开:
interface IBehaviour {
//Extra
foo(param: string): void;
}
interface IModal extends IBehaviour{
content: string;
form: string;
//...
}
On the other hand, for example during unit testing your code (if you may not applying separation of concerns frequently), you may be able to accept the drawbacks for the sake of productivity. You may apply other methods to create mocks mostly for big third party *.d.ts interfaces. And it could be a pain to always implement full anonymous objects for every huge interface.
另一方面,例如在对代码进行单元测试期间(如果您可能不经常应用关注点分离),为了提高生产力,您可能能够接受这些缺点。您可以应用其他方法来创建主要用于大型第三方 *.d.ts 接口的模拟。总是为每个巨大的接口实现完整的匿名对象可能会很痛苦。
On this path your first option is to create an empty object:
在这条路径上,您的第一个选择是创建一个空对象:
var modal = <IModal>{};
Secondly to fully realise the compulsory part of your interface. It can be useful whether you are calling 3rd party JavaScript libraries, but I think you should create a class instead, like before:
其次要完全实现界面的强制部分。无论您是在调用 3rd 方 JavaScript 库,这都会很有用,但我认为您应该像以前一样创建一个类:
var modal: IModal = {
content: '',
form: '',
//...
foo: (param: string): void => {
}
};
Thirdly you can create just a part of your interfaceand create an anonymous object, but this way you are responsible to fulfil the contract
第三,您可以只创建界面的一部分并创建一个匿名对象,但这样您就有责任履行合同。
var modal: IModal = <any>{
foo: (param: string): void => {
}
};
Summarising my answer even if interfaces are optional, because they are not transpiled into JavaScript code, TypeScript is there to provide a new level of abstraction, if used wisely and consistently. I think, just because you can dismiss them in most of the cases from your own code you shouldn't.
总结我的答案,即使接口是可选的,因为它们没有被转换成 JavaScript 代码,如果明智和一致地使用,TypeScript 可以提供一个新的抽象级别。我认为,仅仅因为您可以在大多数情况下从您自己的代码中忽略它们,您不应该这样做。
回答by Kangudie Muanza - Killmonger
You can do
你可以做
var modal = {} as IModal
回答by Zokor
Since I haven't found an equal answer in the top and my answer is different. I do:
由于我没有在顶部找到相同的答案,因此我的答案不同。我愿意:
modal: IModal = <IModal>{}
回答by rbento
Here is another approach:
这是另一种方法:
You can simply create an ESLint friendly object like this
您可以像这样简单地创建一个 ESLint 友好对象
const modal: IModal = {} as IModal;
Or a default instance based on the interface and with sensible defaults, if any
或者基于接口的默认实例和合理的默认值,如果有的话
const defaultModal: IModal = {
content: "",
form: "",
href: "",
$form: {} as JQuery,
$message: {} as JQuery,
$modal: {} as JQuery,
$submits: {} as JQuery
};
Then variations of the default instance simply by overriding some properties
然后简单地通过覆盖一些属性来改变默认实例
const confirmationModal: IModal = {
...defaultModal, // all properties/values from defaultModal
form: "confirmForm" // override form only
}
回答by Byrd
Using your interface you can do
使用你的界面你可以做
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.
}
}
回答by Stephen Paul
Many of the solutions so far posted use type assertions and therefor do not throw compilation errors if required interface properties are omitted in the implementation.
迄今为止发布的许多解决方案都使用类型断言,因此如果在实现中省略了所需的接口属性,则不会引发编译错误。
For those interested in some other robust, compact solutions:
对于那些对其他一些强大、紧凑的解决方案感兴趣的人:
Option 1: Instantiate an anonymous class which implements the interface:
选项 1:实例化一个实现接口的匿名类:
new class implements MyInterface {
nameFirst = 'John';
nameFamily = 'Smith';
}();
Option 2: Create a utility function:
选项 2:创建一个效用函数:
export function impl<I>(i: I) { return i; }
impl<MyInterface>({
nameFirst: 'John';
nameFamily: 'Smith';
})