如何为对象数组定义接口?

Posted

技术标签:

【中文标题】如何为对象数组定义接口?【英文标题】:How can I define an interface for an array of objects? 【发布时间】:2014-10-17 14:52:32 【问题描述】:

我有以下界面和代码。我以为我的定义是正确的,但我得到了一个错误:

interface IenumServiceGetOrderBy  id: number; label: string; key: any [];

和:

getOrderBy = (entity): IenumServiceGetOrderBy => 
        var result: IenumServiceGetOrderBy;
        switch (entity) 
            case "content":
                result =
                [
                     id: 0, label: 'CId', key: 'contentId' ,
                     id: 1, label: 'Modified By', key: 'modifiedBy' ,
                     id: 2, label: 'Modified Date', key: 'modified' ,
                     id: 3, label: 'Status', key: 'contentStatusId' ,
                     id: 4, label: 'Status > Type', key: ['contentStatusId', 'contentTypeId'] ,
                     id: 5, label: 'Title', key: 'title' ,
                     id: 6, label: 'Type', key: 'contentTypeId' ,
                     id: 7, label: 'Type > Status', key: ['contentTypeId', 'contentStatusId'] 
                ];
                break;
        
        return result;
    ;

错误:

Error   190 Cannot convert '[]' to 'IenumServiceGetOrderBy':
    Type '[]' is missing property 'id' from type 'IenumServiceGetOrderBy'

【问题讨论】:

【参考方案1】:

您可以使用indexer 定义接口:

interface EnumServiceGetOrderBy 
    [index: number]:  id: number; label: string; key: any ;

【讨论】:

不是真正的“Typescript 对象数组的接口” 是的,您仅为特定项目定义接口的示例将是一种更有用的方法。拥有一系列项目但又不想方便地引用单个项目的情况非常罕见。使用真实数组也会在接口上暴露 .length,这可能会经常使用。 如何定义类来实现这个接口? 这个解决方案的问题是这不是Array接口,因此所有Array属性和方法如lengthpush都会丢失。 有了这个你会在使用数组函数时出错,看这个 - ***.com/q/50215823/9640177【参考方案2】:

您不需要 使用索引器(因为它的类型安全性稍差)。你有两个选择:

interface EnumServiceItem 
    id: number; label: string; key: any


interface EnumServiceItems extends Array<EnumServiceItem>


// Option A 
var result: EnumServiceItem[] = [
     id: 0, label: 'CId', key: 'contentId' ,
     id: 1, label: 'Modified By', key: 'modifiedBy' ,
     id: 2, label: 'Modified Date', key: 'modified' ,
     id: 3, label: 'Status', key: 'contentStatusId' ,
     id: 4, label: 'Status > Type', key: ['contentStatusId', 'contentTypeId'] ,
     id: 5, label: 'Title', key: 'title' ,
     id: 6, label: 'Type', key: 'contentTypeId' ,
     id: 7, label: 'Type > Status', key: ['contentTypeId', 'contentStatusId'] 
];

// Option B
var result: EnumServiceItems = [
     id: 0, label: 'CId', key: 'contentId' ,
     id: 1, label: 'Modified By', key: 'modifiedBy' ,
     id: 2, label: 'Modified Date', key: 'modified' ,
     id: 3, label: 'Status', key: 'contentStatusId' ,
     id: 4, label: 'Status > Type', key: ['contentStatusId', 'contentTypeId'] ,
     id: 5, label: 'Title', key: 'title' ,
     id: 6, label: 'Type', key: 'contentTypeId' ,
     id: 7, label: 'Type > Status', key: ['contentTypeId', 'contentStatusId'] 
]

我个人推荐选项 A(当您使用类而不是接口时迁移更简单)。

【讨论】:

正在将? 添加到界面中的所有声明中,例如。 id?: number; label?: string; key?: any 如果您使用 less 属性而不是接口中定义的属性,那么避免转换问题的最佳方法是什么? IE。我可能不会在类型化数组设置中指定key 选项 B 很有用,因为它允许您在编写更高级别的接口时使用该接口。 天哪,这困扰了我这么久,谢谢! 第二个接口声明给出以下 tslint 错误:“一个声明没有成员的接口等同于它的超类型 我可以建议'key'是字符串类型吗?字符串 [] 而不是任何。像这样:interface EnumServiceItem id: number; label: string; key: string | string[] 【参考方案3】:

您可以通过简单地扩展 Array 接口将接口定义为数组。

export interface MyInterface extends Array<MyType>  

这样,任何实现MyInterface的对象都需要实现数组的所有函数调用,并且只能存储MyType类型的对象。

【讨论】:

漂亮的解决方案。这应该是公认的答案。 为什么不使用类型 (type MyTypeArray = Array&lt;MyType&gt;) 而不是扩展接口? OP 要求提供接口,我假设它是用其他属性和方法扩展的,你不能用类型来做到这一点,而且在一般可用性方面,类型比接口更受限制 我看了这个,我希望在这个例子中也定义了MyType。我几乎可以使用这个答案,当然,除了我卡住了,因为我不知道MyType 应该是什么样子。是否可以用它来更新答案? 最好的解决方案应该是公认的答案【参考方案4】:

没有 tslint 错误的简单选项 ...

export interface MyItem 
    id: number
    name: string


export type MyItemList = [MyItem]

【讨论】:

导出的MyItemList 类型将是“MyItem 的单元素数组” 可能是export type MyItemList = MyItem[]?。 IMO 接口和类型别名的组合最适合这种情况,因为您的类型别名中包含 Array 类型的所有方法【参考方案5】:

如果你不想创建一个全新的类型,这里有一个内联版本:

export interface ISomeInterface extends Array<
    [someindex: string]: number;
>  ;

【讨论】:

我喜欢这个选项。【参考方案6】:

你也可以这样做。

            interface IenumServiceGetOrderBy 
                id: number; 
                label: string; 
                key: any;
            

            // notice i am not using the []
            var oneResult: IenumServiceGetOrderBy =  id: 0, label: 'CId', key: 'contentId';

            //notice i am using []
            // it is read like "array of IenumServiceGetOrderBy"
            var ArrayOfResult: IenumServiceGetOrderBy[] = 
            [
                 id: 0, label: 'CId', key: 'contentId' ,
                 id: 1, label: 'Modified By', key: 'modifiedBy' ,
                 id: 2, label: 'Modified Date', key: 'modified' ,
                 id: 3, label: 'Status', key: 'contentStatusId' ,
                 id: 4, label: 'Status > Type', key: ['contentStatusId', 'contentTypeId'] ,
                 id: 5, label: 'Title', key: 'title' ,
                 id: 6, label: 'Type', key: 'contentTypeId' ,
                 id: 7, label: 'Type > Status', key: ['contentTypeId', 'contentStatusId'] 
            ];

【讨论】:

【参考方案7】:

其他简单的选项:

    interface simpleInt 
        id: number;
        label: string;
        key: any;
    

    type simpleType = simpleInt[];

【讨论】:

非常好,简单,优雅。【参考方案8】:

在 Angular 中,使用“扩展”来定义对象“数组”的接口。

使用索引器会报错,因为它不是数组接口,因此不包含属性和方法。

例如

错误 TS2339:类型“ISelectOptions2”上不存在属性“find”。

// good    
export interface ISelectOptions1 extends Array<ISelectOption> 

// bad
export interface ISelectOptions2 
    [index: number]: ISelectOption;


interface ISelectOption 
    prop1: string;
    prop2?: boolean;

【讨论】:

如果 linter 不允许空接口,此方法将导致“声明无成员的接口等同于其超类型”。 这个答案非常接近它帮助我解决了我的问题!对于要在另一个接口中为其创建数组的初始对象,键入“interface ISelectOptions name1 : type; name2: type; 然后在 BIG 接口中,当你到达想要成为数组的键时那个类型,keyZ: ISelectOptions[]; 然后当你创建 JSON 时, myVar : BIG = key1: val1, key2: val2, ..., keyZ: [name1 : valA, name2: valB, name1 : valC, name2 : valD] 像冠军一样工作!(虽然不需要扩展 Array 类)谢谢!【参考方案9】:

编程很简单。使用简单的用例:

interface IenumServiceGetOrderBy  id: number; label: string; key: any 
 // OR
interface IenumServiceGetOrderBy  id: number; label: string; key: string | string[] 

// use interface like
const result: IenumServiceGetOrderBy[] = 
                [
                     id: 0, label: 'CId', key: 'contentId' ,
                     id: 1, label: 'Modified By', key: 'modifiedBy' ,
                     id: 4, label: 'Status > Type', key: ['contentStatusId', 'contentTypeId'] 
                ];


【讨论】:

【参考方案10】:

不要使用

interface EnumServiceGetOrderBy 
    [index: number]:  id: number; label: string; key: any ;

您将收到所有 Arrays 属性和方法(例如 splice 等)的错误。

解决方案是创建一个接口,该接口定义另一个接口的数组(将定义对象)

例如:

interface TopCategoriesProps 
  data: Array<Type>;

interface Type 
  category: string;
  percentage: number;

【讨论】:

【参考方案11】:

这是一种适合您的示例的解决方案:

interface IenumServiceGetOrderByAttributes  
  id: number; 
  label: string; 
  key: any 


interface IenumServiceGetOrderBy extends Array<IenumServiceGetOrderByAttributes> 



let result: IenumServiceGetOrderBy;

通过此解决方案,您可以使用 Array 的所有属性和方法(例如: length, push(), pop(), splice() ...)

【讨论】:

【参考方案12】:

这样使用!

interface Iinput 
  label: string
  placeholder: string
  register: any
  type?: string
  required: boolean



// This is how it can be done

const inputs: Array<Iinput> = [
  
    label: "Title",
    placeholder: "Bought something",
    register: register,
    required: true,
  ,
]

【讨论】:

【参考方案13】:

我会使用以下结构:

interface arrayOfObjects extends Array<> 

然后更容易定义:

let myArrayOfObjects: arrayOfObjects = [
   id: 0, label: "CId", key: "contentId" ,
   id: 1, label: "Modified By", key: "modifiedBy" ,
   id: 2, label: "Modified Date", key: "modified" ,
   id: 3, label: "Status", key: "contentStatusId" ,
   id: 4, label: "Status > Type", key: ["contentStatusId", "contentTypeId"] ,
   id: 5, label: "Title", key: "title" ,
   id: 6, label: "Type", key: "contentTypeId" ,
   id: 7, label: "Type > Status", key: ["contentTypeId", "contentStatusId"] ,
];

【讨论】:

以上是关于如何为对象数组定义接口?的主要内容,如果未能解决你的问题,请参考以下文章

如何为包含数组数组的对象编写 Mongoose Schema?

如何为数组中的嵌套数组中的多个对象生成连续索引

如何为数组中的每个对象渲染一个组件?

如何为javascript数组中的每个对象动态添加属性

如何为嵌套的对象数组添加验证

我如何为包含数组数组的对象编写猫鼬模式?