Typescript-arraygränssnitt med numrerat index och anpassade egenskaper åtkomliga via strängnycklar
Jag skulle vilja ha en matris av objekt indexerade med siffror och också lägga alla objekt i matrisen under en specifik nyckel
Något sådant här:
const myArray:ICustomArray = []
myArray.push(item)
myArray[item.key] = item;
Men jag har svårt att definiera dess gränssnitt. Först förväntade jag mig att något sådant här skulle fungera, men det gör det inte.
export interface ICustomArray extends Array<IItem> {
[index: number] : IItem;
[key: string] : IItem;
}
Svar #1
Problemet med din typ är att den är inkonsekvent när det gäller strängindexsignaturen ([key: string] : IItem;). Inte alla nycklar som nås på detta sätt kommer att vara av typen IItem om du ärver en array. Till exempel kommer myArray['map'] att vara array-funktionen och inte IItem. Detta är anledningen till att TypeScript tvingar strängindexsignaturen att vara kompatibel med ALLA statiskt deklarerade medlemmar av gränssnittet.
Det finns dock en kryphål i denna kontroll. Kryphålet med intersection-typen. Vi kan deklarera ICustomArray som en intersection av array och en typ som har indexsignaturen.
export type ICustomArray = Array<IItem> & {
[key: string] : IItem;
}
let item: IItem;
const myArray: ICustomArray = [] as ICustomArray
myArray.push(item)
myArray[item.key] = item;
Detta kommer mestadels att fungera på det sätt du skulle förvänta dig:
let o = myArray['map'] // o is a function of type <U>(callbackfn: (value: IItem, index: number, array: IItem[]) => U, thisArg?: any) => U[]
let i = myArray['key'] //IItem
declare let randomStr: string
let d = myArray[randomStr] //IItem .. but if randomStr= map, we have a runtime problem
Svar #2
Det du gör är konstigt och Typescript-teamet stöder medvetet inte sådana konstiga idéer. Därför måste du göra några konstiga lösningar (förlåt för att jag skrev "konstig" 3 gånger):
interface IItem {
key: string
}
type ICustomArray = Array<IItem> & {
[key: string]: IItem
}
const myArray: ICustomArray = [] as unknown as ICustomArray
myArray.push(item)
myArray[item.key] = item;
Konstigheten ligger i att kombinera array och objekt. Dessutom kan objektet ha vilken nyckel som helst. Det finns inte mycket nytta med ett gränssnitt med godtyckliga nycklar.
