6

Определение типа в объектном литерале в TypeScript

11

Вопрос на StackOverflow:

Я пытаюсь определить тип свойства в объектном литерале в TypeScript, но у меня не получается. В классах TypeScript можно объявлять типы для свойств, например:

class className {
  property: string;
}

Но когда я пытаюсь сделать то же самое для объекта, у меня не получается:

var obj = {
  property: string;
};

Компилятор выдает ошибку:

The name 'string' does not exist in the current scope

Я правильно поступаю, или это ошибка? Как правильно задать тип для свойства в объектных литералах?

4 ответ(ов)

6

Вы почти у цели, вам просто нужно заменить = на :. Вы можете использовать литерал типа объекта (см. раздел 3.5.3 спецификации) или интерфейс. Использование литерала типа объекта похоже на то, что у вас уже есть:

var obj: { property: string; } = { property: "foo" };

Но вы также можете использовать интерфейс:

interface MyObjLayout {
    property: string;
}

var obj: MyObjLayout = { property: "foo" };
3

Обновление 2019-05-15 (Улучшенный шаблон кода в качестве альтернативы)

После многих лет использования const и получения преимуществ от более функционального кода, я бы рекомендовал избегать использования моих первоначальных ответов в большинстве случаев (заголовки ниже этого раздела, например, при создании объектов, указывают на то, что принуждение системы типов к конкретному типу вместо того, чтобы позволить ей выводить типы, часто является признаком того, что что-то не так).

Вместо этого я рекомендую использовать переменные const как можно больше, а затем формировать объект на последнем шаге:

const id = getId();
const hasStarted = true;
...
const hasFinished = false;
...
return { hasStarted, hasFinished, id };
  • Это правильно установит тип для всего без необходимости в явном указании типов.
  • Нет необходимости повторно указывать типы полей.
  • Это приводит к самому чистому коду, исходя из моего опыта.
  • Это позволяет компилятору предоставлять больше проверок состояния (например, если вы возвращаете значение из нескольких мест, компилятор обеспечит возврат одного и того же типа объекта — что побуждает вас объявлять всё возвращаемое значение в каждом месте — придавая совершенно ясное намерение этого значения).

Бонус: Опциональные поля 2022-09-29

const id = getId();
const optionalField = getOptionalValue();
return {
    id,
    // Это всегда будет существовать как ключ в объекте, но может быть неопределено
    optionalField,
    // Это будет существовать как ключ в объекте только если у него есть истинное значение
    ...optionalField2 ? { optionalField } : {},
    // Это будет существовать как ключ в объекте только если он не равен null или undefined
    ...optionalField2 != null ? { optionalField } : {},
};

Добавление 2020-02-26

Если вам действительно нужен тип, который можно инициализировать лениво: обозначьте его как тип объединения, допускающий null (null или Type). Система типов предотвратит использование этого типа без предварительной проверки его значения.

В tsconfig.json убедитесь, что вы включили строгие проверки на null:

"strictNullChecks": true

Затем используйте этот шаблон и позволяйте системе типов защищать вас от случайного доступа к null/undefined:

const state = {
    instance: null as null | ApiService,
    // ИЛИ
    // instance: undefined as undefined | ApiService,
};

const useApi = () => {
    // Если я попытаюсь использовать его здесь, система типов потребует безопасный способ доступа

    // Простая ленивое инициализация 
    const api = state?.instance ?? (state.instance = new ApiService());
    api.fun();

    // Также есть несколько способов получить доступ к нему только если он имеет значение:

    // 'Правильный' способ: требует Typescript 3.7
    state.instance?.fun();

    // Или старый способ: если вы застряли до Typescript 3.7
    state.instance && state.instance.fun();

    // Или самый длинный способ, потому что вышеупомянутое звучит странно
    if (state.instance) { state.instance.fun(); }

    // Или как в C, когда я не могу проверять null как логические значения
    if (state.instance != null) { state.instance.fun(); }

    // Или как в C, когда я не могу проверять null как логические значения 
    // И мне сказали всегда использовать тройное === в javascript даже с проверками на null
    if (state.instance !== null && state.instance !== undefined) { state.instance.fun(); }
};

class ApiService {
    fun() {
        // Сделайте что-то полезное здесь
    }
}

Не делайте ниже в 99% случаев:

Обновление 2016-02-10 - Для обработки TSX (Спасибо @Josh)

Используйте оператор as для TSX.

var obj = {
    property: null as string
};

Длинный пример:

var call = {
    hasStarted: null as boolean,
    hasFinished: null as boolean,
    id: null as number,
};

Оригинальный ответ

Используйте оператор приведения типа, чтобы сделать это кратко (приводя null к нужному типу).

var obj = {
    property: <string> null
};

Длинный пример:

var call = {
    hasStarted: <boolean> null,
    hasFinished: <boolean> null,
    id: <number> null,
};

Это значительно лучше, чем иметь две части (одна для объявления типов, вторая для объявления значений по умолчанию):

var callVerbose: {
    hasStarted: boolean;
    hasFinished: boolean;
    id: number;
} = {
    hasStarted: null,
    hasFinished: null,
    id: null,
};
0

Если вы пытаетесь написать аннотацию типа, синтаксис будет следующим:

var x: { property: string; } = { property: 'hello' };

Если вы пытаетесь написать объектное литерал, синтаксис будет таким:

var x = { property: 'hello' };

Ваш код пытается использовать имя типа в позиции значения.

0

Если вы пытаетесь добавить типизацию к деструктурированному объекту, например, при передаче аргументов в функцию, синтаксис будет следующим:

function foo({ bar, baz }: { bar: boolean; baz: string }) {
  // ...
}

foo({ bar: true, baz: 'lorem ipsum' });

Таким образом, вы можете указать, какие типы данных ожидаются для свойств bar и baz в объекте, который передается в функцию.

Чтобы ответить на вопрос, пожалуйста, войдите или зарегистрируйтесь