Användning av typad array i TypeScript


Jag har en TypeScript-klassdefinition som börjar så här;

module Entities {          

    export class Person {
        private _name: string;
        private _possessions: Thing[];
        private _mostPrecious: Thing;

        constructor (name: string) {
            this._name = name;
            this._possessions = new Thing[100];
        }

Det ser ut som en array av typen Thing inte översätts korrekt till den motsvarande Javascript-arraytypen. Detta är ett utdrag från den genererade JavaScript:

function Person(name) {
    this._name = name;
    this._possessions = new Entities.Thing[100]();
}

Körning av kod som innehåller ett Person-objekt, kasta ett undantag när du försöker initiera _possession-fältet:

Fel är "0x800a138f - Microsoft JScript-körtidsfel: Kan inte hämta värdet av egenskapen '100': objektet är null eller odefinierat".

Om jag ändrar typen på _possession till any[] och initierar _possession med new Array() kastas inget undantag. Missade jag något?

Svar #1

Du har ett fel i din syntax här:

this._possessions = new Thing[100]();

Detta skapar inte en "matris av saker". För att skapa en matris av saker kan du helt enkelt använda matrisliteraluttrycket:

this._possessions = [];

Av array-konstruktorn om du vill ställa in längden:

this._possessions = new Array(100);

Jag har skapat ett kort arbetsprov som du kan prova i lekområdet.

module Entities {  

    class Thing {

    }        

    export class Person {
        private _name: string;
        private _possessions: Thing[];
        private _mostPrecious: Thing;

        constructor (name: string) {
            this._name = name;
            this._possessions = [];
            this._possessions.push(new Thing())
            this._possessions[100] = new Thing();
        }
    }
}

Svar #2

Det finns två syntaxalternativ tillgängliga när man deklarerar en array i TypeScript. TypeScript-dokumentationen använder Array<T> men TS-Lint föredrar T[]

Genom att använda Array<Thing> utnyttjas generics i TypeScript. Det är liknande som att begära en List<T> i C#-kod.

// Declare with default value
private _possessions: Array<Thing> = new Array<Thing>(); // or
private _possessions: Array<Thing> = []; // or
private _possessions: Thing[] = []; // or -> prefered by ts-lint

eller

// declare then assign in the constructor
private _possessions: Array<Thing>; // or
private _possessions: Thing[]; // or -> preferd by ts-lint
  
constructor(){
    this._possessions = new Array<Thing>(); // or
    this._possessions = []; // or
}

Svar #3

Översättningen är korrekt, men typningen av uttrycket är det inte. TypeScript typar felaktigt uttrycket new Thing[100] som en array. Det borde vara ett fel att indexera Thing, en konstruktionsfunktion, med indexoperatorn. I C# skulle detta allokera en array med 100 element. I JavaScript anropar detta värdet på index 100 av Thing som om det var en konstruktor. Eftersom det värdet är undefined uppstår det fel du nämnde. I JavaScript och TypeScript vill du istället använda new Array(100).

Du bör rapportera detta som ett fel på CodePlex.

Relaterade artiklar