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

В TypeScript в классе можно объявить тип для свойства, например:

class className{
    property : string;
};

Как я должен написать код, чтобы объявить тип для свойства в литерал объекта? Такой код не компилируется:

var obj = {
    property: string;
};

(Я получаю сообщение об ошибке - имя "строка" не существует в текущей области).

Что я делаю не так или это баг?

15 ответов

Решение

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

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

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

interface MyObjLayout {
    property: string;
}

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

Используйте оператор приведения, чтобы сделать это кратким (приведя значение 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,
};

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

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

var obj = {
    property: null as string
};

Более длинный пример:

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

Я удивлен, что никто не упомянул об этом, но вы могли бы просто создать один интерфейс под названием ObjectLiteral, как это:

interface ObjectLiteral {
  [key: string]: any;
}

Тогда вы бы использовали его, вот так:

let data: ObjectLiteral = {
  hello: "world",
  goodbye: 1,
  // ...
};

Вы можете повторно использовать этот единственный интерфейс много раз, как захотите.

Удачи.

Если ваши свойства имеют один и тот же тип, вы можете использовать предопределенный тип утилиты Record:

type Keys = "property" | "property2"

const obj: Record<Keys, string> = {
  property: "my first prop",
  property2: "my second prop",
};

Конечно, вы можете пойти дальше и определить собственный тип для значений свойств:

type Keys = "property" | "property2"
type Values = "my prop" | "my other allowed prop"

const obj: Record<Keys, Values> = {
  property: "my prop",
  property2: "my second prop", // TS Error: Type '"my second prop"' is not assignable to type 'Values'.
};

Если вы пытаетесь написать аннотацию типа, синтаксис:

var x: { property: string; } = ...;

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

var x = { property: 'hello' };

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

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

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

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

В машинописи, если мы объявляем объект, то

[модификатор доступа] имя переменной: { // структура объекта}

private Object:{Key1:string , Key2:number }

Остерегаться. Некоторым это может показаться очевидным, но объявление типа

      const foo:TypeName = {}

это не то же самое по сравнению с литьем с as

      const foo = {} as TypeName

несмотря на предложения использовать другие ответы.

Пример:

      const foo: { [K in 'open' | 'closed']: string } = {}
// ERROR: TS2739: Type '{}' is missing the following properties from type '{ open: string; closed: string; }': open, closed

Спасибо, безопасность типов!

      const foo = {} as { [K in 'open' | 'closed']: string }
// No error

Прощай, безопасность типов!

Вот что я делаю в 2021 году:

      const sm = {
  currentCacheName: '' as string,
  badSWTimer: 0 as number,
  reg: {} as ServiceWorkerRegistration,
  quantum: null as number | null
}

Это не просто приведение значения, оно работает так же, как определение интерфейса для свойств объекта.

// Use ..

const Per = {
  name: 'HAMZA',
  age: 20,
  coords: {
    tele: '09',
    lan: '190'
  },
  setAge(age: Number): void {
    this.age = age;
  },
  getAge(): Number {
    return age;
  }
};
const { age, name }: { age: Number; name: String } = Per;
const {
  coords: { tele, lan }
}: { coords: { tele: String; lan: String } } = Per;

console.log(Per.getAge());

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

      interface NameInfo {
  first: string;
  last: string | undefined;
}
const people = {
  john: { first: "John", last: "Doe" },
  jane: { first: "Jane", last: "Doe" } satisfies NameInfo,
} satisfies Record<string, NameInfo>;

Другой вариант — создать класс со статическими свойствами:

      class TestData {
  static people: Record<string, NameInfo> = {
    john: { first: "John", last: "Doe" },
    jane: { first: "Jane", last: "Doe" },
  };
}

В вашем коде:

var obj = {
  myProp: string;
};

Фактически вы создаете литерал объекта и назначаете переменную строку свойству myProp. Хотя это очень плохая практика, на самом деле это будет действительный код TS (не используйте его!):

var string = 'A string';

var obj = {
  property: string
};

Однако вы хотите, чтобы литерал объекта был типизирован. Этого можно добиться разными способами:

Интерфейс:

interface myObj {
    property: string;
}

var obj: myObj = { property: "My string" };

Пользовательский тип:

type myObjType = {
    property: string
};

var obj: myObjType = { property: "My string" };

Оператор приведения:

var obj = {
    myString: <string> 'hi',
    myNumber: <number> 132,
};

Литерал типа объекта:

var obj: { property: string; } = { property: "Mystring" };
  1. создать тип с помощью ключевого слова типа
      type ObjType = {
  property: string;
}

а затем вы можете использовать его для привязки вашего объекта, чтобы он принимал только этот тип, как показано ниже.

      const obj: ObjType = {
property: "TypeScript"
}

Просто чтобы расширить ответ @RickLove...

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

      const initialState = { 
   user: undefined as User | undefined, 
   userLoading: false
}; 

и он преобразуется в этот код js:

      const initialState = { 
   user: undefined, 
   userLoading: false
};  

И если вам нужно извлечь его в тип, вы можете просто сделать это:

      export type InitState = typeof initialState;

Преобразование литерала объекта в тип с помощью DRY

Просто делать:

      const myObject = {
   hello: 'how are you',
   hey: 'i am fine thank you'
}
      type myObjectType = keyof typeof MyObject

Работа сделана!

Другие вопросы по тегам