【问题标题】: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'

【问题讨论】:

    标签: typescript


    【解决方案1】:

    您可以使用indexer 定义接口:

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

    【讨论】:

    • 不是真正的“Typescript 对象数组的接口”
    • 是的,您仅为特定项目定义接口的示例将是一种更有用的方法。拥有一系列项目但又不想方便地引用单个项目的情况非常罕见。使用真实数组也会在接口上暴露 .length,这可能会经常使用。
    • 如何定义类来实现这个接口?
    • 这个解决方案的问题是这不是Array接口,因此所有Array属性和方法如lengthpush都会丢失。
    • 有了这个你会在使用数组函数时出错,看这个 - stackoverflow.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"] },
              ];
              

              【讨论】:

                猜你喜欢
                • 2023-01-05
                • 1970-01-01
                • 2017-07-02
                • 1970-01-01
                • 1970-01-01
                • 2021-12-08
                • 2023-04-05
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多