Typescript ile bir nesne dizisi için bir arabirimi nasıl tanımlayabilirim?


115

Aşağıdaki arayüz ve koda sahibim. Tanımları doğru yaptığımı sanıyordum ama bir hata alıyorum:

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

ve:

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

Hata:

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

Yanıtlar:


101

Bir indeksleyici ile bir arayüz tanımlayabilirsiniz :

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

35
Gerçekte "
Typescript

Evet, sadece belirli öğeler için bir arayüz tanımlama örneğiniz, bunu yapmanın daha kullanışlı bir yolu olacaktır. Bir dizi öğeye sahip olmak oldukça nadirdir, ancak tek bir öğeye uygun şekilde atıfta bulunmak istemez. Gerçek bir dizi kullanmak, muhtemelen oldukça sık kullanılacak olan arabirimde .length'i de ortaya çıkarır.
Douglas

Bu arayüzü tamamlamak için sınıf nasıl tanımlanır?
alexey

19
Bu çözümle ilgili sorun, bunun bir Arrayarayüz olmamasıdır , bu nedenle gibi tüm Arrayözellikler ve yöntemler gibi lengthveya pusheksik olacaktır.
Norman Breau

221

Bir dizin oluşturucu kullanmanıza gerek yoktur (çünkü biraz daha az tür güvenlidir). İki seçeneğiniz var:

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'] }
]

Kişisel olarak, Seçenek A'yı tavsiye ederim (arayüzleri değil sınıfları kullandığınızda daha basit geçiş).


3
?Arayüzdeki tüm bildirimlere ekliyor , örn. Arayüzde tanımlanandan daha az özellik id?: number; label?: string; key?: anykullanıyorsanız, bir çevrim sorununu önlemenin en iyi yolu nedir? Yani. Yazılan dizi kurulumunda belirtemeyebilirim . key
GONeale

Seçenek B, üst düzey arayüzler oluştururken arayüzü kullanmanıza izin verdiği için kullanışlıdır.
aashtonk

1
Tanrım, bu beni çok uzun zamandır rahatsız etti, teşekkürler!
Matthew Harwood

2
İkinci arayüz bildirimi şu tslint hatasını veriyor: " hiçbir üye bildirmeyen bir arayüz, süper tipine eşdeğerdir "
Inigo

2
"Key" dizesi türünde olduğunu önerebilir miyim | herhangi biri yerine string []. Bunun gibi: interface EnumServiceItem { id: number; label: string; key: string | string[] }
JulianG

79

Array arayüzünü basitçe genişleterek bir arayüzü dizi olarak tanımlayabilirsiniz.

export interface MyInterface extends Array<MyType> { }

Bununla, uygulayan herhangi bir nesne MyInterface, dizilerin tüm işlev çağrılarını gerçekleştirmeye ihtiyaç duyacak ve yalnızca MyTypetürdeki nesneleri depolayabilecektir .


6
Güzel çözüm. Kabul edilen cevap bu olmalıdır.
demisx

2
type MyTypeArray = Array<MyType>Arayüzü genişletmek yerine neden bir tür ( ) kullanılmasın?
Pau Fracés

OP arayüz istedi, diğer özellikler ve yöntemlerle genişletildiğini varsayıyorum, bunu bir
türle yapamazsınız

@NoNameProvided "türü, genel kullanılabilirlik açısından bir arabirimden daha sınırlıdır" Bu ifadeyle ilgili daha fazla ayrıntı verebilir misiniz? Türleri arabirimlere karşı kullanmanın sınırlamaları nelerdir?
Pau Fracés

1
Diğerlerinden daha iyi çözüm kabul edilen cevap olmalıdır
Andres Felipe

17

Ek kolay seçenek:

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

    type simpleType = simpleInt[];

8

Kullanmayın

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

Tüm Arrays özellikleri ve splice vb. Yöntemler için hatalar alacaksınız.

Çözüm, başka bir arabirim dizisini tanımlayan (nesneyi tanımlayacak) bir arabirim oluşturmaktır.

Örneğin:

interface TopCategoriesProps {
  data: Array<Type>;
}
interface Type {
  category: string;
  percentage: number;
}

4

Açısal kullanımda, nesnelerin bir 'Dizisi' için arabirimi tanımlamak için 'genişler'.

Bir dizin oluşturucu kullanmak, bir Array arayüzü olmadığından, özellikleri ve yöntemleri içermediğinden size bir hata verecektir.

Örneğin

hatası TS2339: 'bul' özelliği 'ISelectOptions2' türünde mevcut değil.

// good    
export interface ISelectOptions1 extends Array<ISelectOption> {}

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

interface ISelectOption {
    prop1: string;
    prop2?: boolean;
}

Linter boş arabirimlere izin vermiyorsa, bu yöntem "Hiçbir üye bildiren bir arabirim, üst türüne eşdeğer değildir" ile sonuçlanır.
demisx

Bu cevap soooo kapatıldı, sorunumu çözmeme yardımcı oldu! Başka bir arabirim içinde bir dizi oluşturmak istediğiniz ilk nesne için, "arabirim ISelectOptions {ad1: tür; ad2: tür;} yazarsınız, ardından BÜYÜK arabiriminizde, bir dizi olmak istediğiniz anahtara vardığınızda bu tür, keyZ: ISelectOptions []; ardından JSON'u oluşturduğunuzda, myVar: BIG = {key1: val1, key2: val2,…, keyZ: [{name1: valA, name2: valB}, {name1: valC, name2 : valD}] bir şampiyon gibi çalıştı! (yine de Array sınıfını genişletmeye gerek yoktu) Teşekkürler!
AppDreamer

3

Bunu da yapabilirsiniz.

            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'] }
            ];

2

Tslint hatası olmayan kolay seçenek ...

export interface MyItem {
    id: number
    name: string
}

export type MyItemList = [MyItem]

5
Dışa aktarılan MyItemListtür "tek öğeli bir dizi MyItem" olacaktır
NoNameProvided

5
Olabilir mi export type MyItemList = MyItem[]? IMO Bir arabirim ve tür takma adının birleşimi, tür takma adınızda Array türünün tüm yöntemlerine sahip olduğunuz için bu durum için en uygun
olanıdır

2

Tamamen yeni bir tür oluşturmak istemiyorsanız, işte bir satır içi sürüm:

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

0

Programlama basittir. Basit kullanım alanı kullanın:

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'] }
                ];


0

İşte örneğinize uyarlanmış bir çözüm:

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

interface IenumServiceGetOrderBy extends Array<IenumServiceGetOrderByAttributes> {

}
let result: IenumServiceGetOrderBy;

Bu çözümle, Dizinin tüm özelliklerini ve yöntemlerini kullanabilirsiniz (örneğin: length, push(), pop(), splice()...)

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.