Як я можу визначити масив об'єктів?


199

Я створюю масив об'єктів у TypeScript:

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

Хтось може сказати мені, як я міг правильно оголосити його тип? Чи можна робити вбудований чи потрібні два визначення?

Я хочу замінити xxxдекларацію типу, щоб пізніше TypeScript попередив мене, якщо я використовував щось подібне userTestStatus[3].nammmeпомилково.

Відповіді:


283

Вам краще використовувати власний масив замість об'єкта, буквального з властивостями, схожими на число, так що нумерація (як і численні інші функції масиву) дбають про позачергові.

Що ви шукаєте тут, це визначення вбудованого інтерфейсу для вашого масиву, який визначає кожен елемент у цьому масиві, спочатку присутній чи введений пізніше:

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 [...]

Якщо ви ініціалізуєте свій масив зі значеннями одразу, явне визначення типу не є необхідністю; TypeScript може автоматично зробити висновок більшості типів елементів з початкового призначення:

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

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

4
Також ви можете оголосити масив об'єктів таким чином:let someArray: Array<{ id: number, name: string }> = []
— Олександр Кім,

77

Ви маєте вище об'єкт, а не масив.

Щоб створити масив, використовуйте [& ]для оточення ваших об'єктів.

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

Крім цього TypeScript є набором JavaScript, тому незалежно від того, який би JavaScript був дійсним, буде дійсним TypeScript, тому інших змін не потрібно.

Пояснення зворотного зв’язку з ОП ... потребує визначення моделі, розміщеної у розміщенні

Ви можете використовувати типи, визначені тут, для представлення вашої об'єктної моделі:

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

Вибачте, можливо, моє запитання було незрозумілим. Що я хотів зробити, це знайти визначення для userTestStatus.

1
@Marilou Визначення зазвичай можна отримати просто наведення курсору на userTestStatusзмінну у вашому улюбленому IDE ... показує майданчик TypeScript { id: number, name: string; }[]. Ви можете обернути це в інтерфейс, якщо вам подобається interface NameThis { id: number, name: string; }і NameThis[]як тип масиву.
— Фентон

Я спробував це, але це дає мені кілька помилок. Однак я думаю, що це щось схоже на мене: userTestStatus: {id: number, name: string; } [] = {"0": {"id": 0, "name": "Доступно"}, "1": {"id": 1, "name": "Ready"},

У вашому прикладі визначення var arr: MyType, ви б не використовували декларації імені властивості / індексу, такі як "0": { … }; Ви просто використовуєте об'єкт буквально в цей момент.
— gfullam

@gfullam ви маєте рацію, я оновив свою відповідь (це була швидка необережна редакція)
— Брокко

36

Деякі tslintправила вимикають використання [], наприклад повідомлення:Array type using 'T[]' is forbidden for non-simple types. Use 'Array<T>' instead.

Тоді ви б написали це так:

var userTestStatus: Array<{ id: number, name: string }> = Array(
    { "id": 0, "name": "Available" },
    { "id": 1, "name": "Ready" },
    { "id": 2, "name": "Started" }
);

2
Самий практичний підхід коли-небудь. це просте і пряме рішення для простих випадків використання масиву. Візьміть мій +1
— Julio Vedovatto

18

Те, що ви дійсно хочете, може бути просто перерахуванням

Якщо ви шукаєте те, що поводиться як перерахування (тому що я бачу, ви визначаєте об'єкт і додаєте послідовний ідентифікатор 0, 1, 2 і містить поле імені, яке ви не хочете неправильно написати (наприклад, ім'я проти naaame) , вам краще визначити перерахування, оскільки послідовний ідентифікатор береться автоматично і забезпечує перевірку типу для вас поза полем.

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

Наведені вище значення будуть автоматично відображатися, наприклад, "0" для "Доступно", і ви можете отримати доступ до них за допомогою TestStatus.Available. І Typescript буде застосовувати тип, коли ви передаєте їх навколо.

Якщо ви наполягаєте на визначенні нового типу як масиву вашого власного типу

Ви хотіли масив об’єктів (не зовсім об'єкт з ключами "0", "1" і "2"), тож давайте визначимо спочатку тип об'єкта, а потім тип масиву, що містить.

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")
]

Вибачте, можливо, моє запитання було незрозумілим. Що я хотів зробити, це знайти визначення для userTestStatus, щоб Typescript дозволив мені перевірити, де він використовується, і, наприклад, я не міг ввести userTestStatus [1] .naaaame.

Я хотів знайти щось, що можна помістити між "userTestStatus" та "=". Точно так само, як я можу поставити туди рядок або число, щоб сказати, який тип має змінна. Щось на зразок Брокко щойно робив, але лише одним рядком, якщо це можливо.

-1

Ви також можете спробувати

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

Щоб перевірити, як працює запис: https://www.typescriptlang.org/docs/handbook/utility-types.html#recordkt

Тут у нашому випадку Record використовується для оголошення об’єкта, чиїм ключем буде рядок і значення якого буде мати тип IData, тому тепер він надасть нам інтелігенцію, коли ми спробуємо отримати доступ до його властивості та викине помилку типу, якщо ми спробуємо щось на зразок userTestStatus [0] .nameee


Ви повинні дати більше інформації, чому це вирішує проблему
— Корнель Райу
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.