¿Cómo puedo definir una matriz de objetos?

197

Estoy creando una matriz de objetos en TypeScript:

 userTestStatus xxxx = {
    "0": { "id": 0, "name": "Available" },
    "1": { "id": 1, "name": "Ready" },
    "2": { "id": 2, "name": "Started" }
 };

¿Alguien puede decirme cómo podría declarar su tipo correctamente? ¿Es posible hacerlo en línea o necesitaría dos definiciones?

Estoy buscando reemplazar el xxxcon una declaración de tipo, para que más adelante TypeScript me avise si usé algo como userTestStatus[3].nammmepor error.

Alexander Abakumov
fuente

Respuestas:

279

Es mejor usar una matriz nativa en lugar de un literal de objeto con propiedades similares a números, de modo que la numeración (así como muchas otras funciones de la matriz) se ocupan de forma inmediata.

Lo que está buscando aquí es una definición de interfaz en línea para su matriz que defina cada elemento en esa matriz, ya sea que esté inicialmente presente o que se presente más tarde:

let userTestStatus: { id: number, name: string }[] = [
    { "id": 0, "name": "Available" },
    { "id": 1, "name": "Ready" },
    { "id": 2, "name": "Started" }
];

userTestStatus[34978].nammme; // Error: Property 'nammme' does not exist on type [...]

Si está inicializando su matriz con valores de inmediato, la definición de tipo explícita no es necesaria; TypeScript puede inferir automáticamente la mayoría de los tipos de elementos de la asignación inicial:

let userTestStatus = [
    { "id": 0, "name": "Available" },
    ...
];

userTestStatus[34978].nammme; // Error: Property 'nammme' does not exist on type [...]
John Weisz
fuente
44
También puede declarar una serie de objetos de esta manera:let someArray: Array<{ id: number, name: string }> = []
Alexander Kim
74

Lo que tienes arriba es un objeto, no una matriz.

Para hacer una matriz, use [& ]para rodear sus objetos.

userTestStatus = [
  { "id": 0, "name": "Available" },
  { "id": 1, "name": "Ready" },
  { "id": 2, "name": "Started" }
];

Aparte de eso, TypeScript es un superconjunto de JavaScript, por lo que todo lo que sea válido JavaScript será TypeScript válido, por lo que no se necesitan otros cambios.

Aclaración de comentarios de OP ... que necesita una definición para el modelo publicado

Puede usar los tipos definidos aquí para representar su modelo de objeto:

type MyType = {
    id: number;
    name: string;
}

type MyGroupType = {
    [key:string]: MyType;
}

var obj: MyGroupType = {
    "0": { "id": 0, "name": "Available" },
    "1": { "id": 1, "name": "Ready" },
    "2": { "id": 2, "name": "Started" }
};
// or if you make it an array
var arr: MyType[] = [
    { "id": 0, "name": "Available" },
    { "id": 1, "name": "Ready" },
    { "id": 2, "name": "Started" }
];
Brocco
fuente
Lo siento, tal vez mi pregunta no estaba clara. Lo que quería hacer era encontrar una definición para userTestStatus.
1
@ Marilou Por lo general, puede obtener la definición simplemente pasando el cursor sobre la userTestStatusvariable en su IDE favorito ... se muestra el patio de juegos TypeScript { id: number, name: string; }[]. Podría envolverlo en una interfaz si lo desea interface NameThis { id: number, name: string; }y NameThis[]como el tipo de matriz.
Fenton
Intenté esto pero me da algunos errores. Sin embargo, creo que es algo como lo que quiero: userTestStatus: {id: number, name: string; } [] = {"0": {"id": 0, "nombre": "Disponible"}, "1": {"id": 1, "nombre": "Listo"},
En su definición de ejemplo var arr: MyType, no usaría el nombre de propiedad / declaraciones de índice como "0": { … }; simplemente usarías el objeto literal en este punto.
gfullam
@gfullam tienes razón, actualicé mi respuesta (fue una edición rápida y descuidada)
Brocco
34

Algunas tslintreglas deshabilitan el uso de [], mensaje de ejemplo:Array type using 'T[]' is forbidden for non-simple types. Use 'Array<T>' instead.

Entonces lo escribirías como:

var userTestStatus: Array<{ id: number, name: string }> = Array(
    { "id": 0, "name": "Available" },
    { "id": 1, "name": "Ready" },
    { "id": 2, "name": "Started" }
);
Ogglas
fuente
2
El enfoque más práctico de la historia. Es una solución simple y directa para casos de uso de matriz simple. Tome mi +1
Julio Vedovatto
16

Lo que realmente quieres puede ser simplemente una enumeración

Si está buscando algo que se comporte como una enumeración (porque veo que está definiendo un objeto y adjuntando un ID secuencial 0, 1, 2 y contiene un campo de nombre que no desea escribir mal (por ejemplo, nombre vs nombre) , es mejor que defina una enumeración porque la identificación secuencial se ocupa automáticamente y proporciona una verificación de tipo de forma inmediata.

enum TestStatus {
    Available,     // 0
    Ready,         // 1
    Started,       // 2
}

class Test {
    status: TestStatus
}

var test = new Test();
test.status = TestStatus.Available; // type and spelling is checked for you,
                                    // and the sequence ID is automatic

Los valores anteriores se asignarán automáticamente, por ejemplo, "0" para "Disponible", y puede acceder a ellos mediante TestStatus.Available. Y Typecript impondrá el tipo cuando pases esos.

Si insiste en definir un nuevo tipo como una matriz de su tipo personalizado

Querías una matriz de objetos (no exactamente un objeto con las teclas "0", "1" y "2"), así que definamos primero el tipo de objeto, luego un tipo de matriz que contiene.

class TestStatus {
    id: number
    name: string

    constructor(id, name){
        this.id = id;
        this.name = name;
    }
}

type Statuses = Array<TestStatus>;

var statuses: Statuses = [
    new TestStatus(0, "Available"),
    new TestStatus(1, "Ready"),
    new TestStatus(2, "Started")
]
bakkal
fuente
Lo siento, tal vez mi pregunta no estaba clara. Lo que quería hacer era encontrar una definición para userTestStatus para que Typecript me permitiera verificar dónde se usa y, por ejemplo, no podría ingresar userTestStatus [1] .naaaame.
Quería encontrar algo para poner entre el "userTestStatus" y el "=". De la misma manera que podría poner cadena o número allí para decir qué tipo tiene la variable. Algo como Brocco acaba de hacer pero con solo una línea si eso es posible.
-1

También puedes probar

    interface IData{
        id: number;
        name:string;
    }

    let userTestStatus:Record<string,IData> = {
        "0": { "id": 0, "name": "Available" },
        "1": { "id": 1, "name": "Ready" },
        "2": { "id": 2, "name": "Started" }
    };

Para verificar cómo funciona el registro: https://www.typescriptlang.org/docs/handbook/utility-types.html#recordkt

Aquí, en nuestro caso, Record se usa para declarar un objeto cuya clave será una cadena y cuyo valor será de tipo IData, por lo que ahora nos proporcionará inteligencia cuando intentemos acceder a su propiedad y arrojemos un error de tipo en caso de que lo intentemos algo así como userTestStatus [0] .nameee

Akash Singh
fuente
debería dar más información sobre por qué esto resuelve el problema en cuestión
Cornel Raiu