Как я могу определить массив объектов?


200

Я создаю массив объектов в TypeScript:

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

Может кто-нибудь сказать мне, как я мог бы правильно объявить его тип? Можно ли сделать inline или мне нужно два определения?

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

Ответы:


285

Вам лучше использовать собственный массив вместо литерала объекта со свойствами, подобными числам, так что нумерация (как и многие другие функции массива) позаботится о готовом продукте.

Здесь вы ищете определение встроенного интерфейса для вашего массива, которое определяет каждый элемент в этом массиве, независимо от того, присутствует он изначально или представлен позже:

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": "Available"}, "1": {"id": 1, "name": "Ready"},

В вашем примере определения var arr: MyTypeвы не будете использовать объявления имени / индекса свойства, такие как "0": { … }; Вы бы просто использовали объектный литерал в этой точке.
gfullam

@gfullam вы правы, я обновил свой ответ (это было быстрое небрежное редактирование)
Brocco

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
Хулио Ведоватто

18

То, что вы действительно хотите, может быть просто перечислением

Если вы ищете что-то, что ведет себя как перечисление (потому что я вижу, что вы определяете объект и присоединяете последовательный идентификатор 0, 1, 2 и содержат поле имени, которое вы не хотите опечатывать (например, name vs 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» и «=». Точно так же, как я мог бы поместить туда строку или число, чтобы сказать, какой тип имеет переменная. Нечто похожее на Brocco, но только с одной строкой, если это возможно.

-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, так что теперь он предоставит нам intellisense, когда мы попытаемся получить доступ к его свойству, и выдаст ошибку типа в случае, если мы попробуем что-то вроде userTestStatus [0] .nameee


Вы должны дать больше информации о том, почему это решает проблему под рукой
Cornel
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.