Как динамически назначать свойства объекту в TypeScript?

Если бы я хотел программно назначить свойство для объекта в Javascript, я бы сделал это следующим образом:

var obj = {};
obj.prop = "value";

Но в TypeScript это порождает ошибку:

Свойство 'prop' не существует при значении типа '{}'

Как мне назначить какое-либо новое свойство объекту в TypeScript?

Ответ 1

Обозначение obj можно обозначить как any, но это побеждает всю цель использования typescript. obj = {} означает, что obj является Object. Пометка как any не имеет смысла. Для достижения желаемой консистенции интерфейс можно определить следующим образом.

interface LooseObject {
    [key: string]: any
}

var obj: LooseObject = {};

ИЛИ сделать его компактным:

var obj: {[k: string]: any} = {};

LooseObject может принимать поля с любой строкой в ​​качестве ключа, а any - как значение.

obj.prop = "value";
obj.prop2 = 88;

Реальная элегантность этого решения заключается в том, что вы можете включать в интерфейс типы полей.

interface MyType {
    typesafeProp1?: number,
    requiredProp1: string,
    [key: string]: any
}

var obj: MyType ;
obj = { requiredProp1: "foo"}; // valid
obj = {} // error. 'requiredProp1' is missing
obj.typesafeProp1 = "bar" // error. typesafeProp1 should be a number

obj.prop = "value";
obj.prop2 = 88;

Ответ 2

Или все за один раз:

  var obj:any = {}
  obj.prop = 5;

Ответ 3

Я склонен ставить any с другой стороны, т.е. var foo:IFoo = <any>{}; Итак, что-то вроде этого все еще существует:

interface IFoo{
    bar:string;
    baz:string;
    boo:string;     
}

// How I tend to intialize 
var foo:IFoo = <any>{};

foo.bar = "asdf";
foo.baz = "boo";
foo.boo = "boo";

// the following is an error, 
// so you haven't lost type safety
foo.bar = 123; 

В качестве альтернативы вы можете пометить эти свойства как необязательные:

interface IFoo{
    bar?:string;
    baz?:string;
    boo?:string;    
}

// Now your simple initialization works
var foo:IFoo = {};

Попробуйте в Интернете

Ответ 4

Это решение полезно, когда ваш объект имеет определенный тип. Например, при получении объекта другому источнику.

let user: User = new User();
(user as any).otherProperty = 'hello';
//user did not lose its type here.

Ответ 5

Хотя компилятор жалуется, он все равно должен выводить его по мере необходимости. Однако это будет работать.

var s = {};
s['prop'] = true;

Ответ 6

Еще один вариант: доступ к свойству в виде коллекции:

var obj = {};
obj['prop'] = "value";

Ответ 7

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

interface MyObject {
    prop1: string;
}

const myObj: MyObject = {
    prop1: 'foo',
}

const newObj = {
    ...myObj,
    prop2: 'bar',
}

console.log(newObj.prop2); // 'bar'

TypeScript выведет все поля исходного объекта, а VSCode сделает автозаполнение и т.д.

Ответ 8

Можно добавить члена к существующему объекту

  1. расширение типа (читай: расширять/специализировать интерфейс)
  2. приведите исходный объект к расширенному типу
  3. добавить член к объекту
interface IEnhancedPromise<T> extends Promise<T> {
    sayHello(): void;
}

const p = Promise.resolve("Peter");

const enhancedPromise = p as IEnhancedPromise<string>;

enhancedPromise.sayHello = () => enhancedPromise.then(value => console.info("Hello " + value));

// eventually prints "Hello Peter"
enhancedPromise.sayHello();

Ответ 9

Javascript:

myObj.myProperty = 1;

Машинопись:

myObj['myProperty'] = 1;

Ответ 10

Сохраните любое новое свойство на любом объекте, указав его на "any":

var extend = <any>myObject;
extend.NewProperty = anotherObject;

Позже вы можете получить его, отбросив расширенный объект до "any":

var extendedObject = <any>myObject;
var anotherObject = <AnotherObjectType>extendedObject.NewProperty;

Ответ 11

Чтобы гарантировать, что тип представляет собой Object (то есть пары ключ-значение), используйте:

const obj: {[x: string]: any} = {}
obj.prop = 'cool beans'

Ответ 12

  • Случай 1:

    var car = {type: "BMW", model: "i8", color: "white"}; car['owner'] = "ibrahim";//You can add a property:

  • Случай 2:

    var car:any = {type: "BMW", model: "i8", color: "white"}; car.owner = "ibrahim";//You can set a property: use any type

Ответ 13

Я удивлен, что ни один из ответов не ссылается на Object.assign с тех пор, как я использую технику, когда я думаю о "композиции" в JavaScript.

И это работает как положено в TypeScript:

interface IExisting {
    userName: string
}

interface INewStuff {
    email: string
}

const existingObject: IExisting = {
    userName: "jsmith"
}

const objectWithAllProps: IExisting & INewStuff = Object.assign({}, existingObject, {
    email: "[email protected]"
})

console.log(objectWithAllProps.email); // [email protected]

преимущества

  • Тип безопасности во всем, потому что вам не нужно использовать any тип вообще
  • использует агрегатный тип TypeScript (как обозначено символом & при объявлении типа objectWithAllProps), который четко сообщает, что мы создаем новый тип на лету (то есть динамически)

Что нужно знать

  1. Object.assign имеет свои уникальные аспекты (которые хорошо известны большинству опытных разработчиков JS), которые следует учитывать при написании TypeScript.
    • Он может быть изменчивым или неизменным (я демонстрирую неизменный способ выше, что означает, что existingObject объект остается неизменным и, следовательно, не имеет свойства email. Для большинства программистов функционального стиля это хорошая вещь, так как результат - единственное новое изменение).
    • Object.assign работает лучше всего, когда у вас есть более плоские объекты. Если вы объединяете два вложенных объекта, которые содержат обнуляемые свойства, вы можете в итоге перезаписать истинные значения неопределенными. Если вы следите за порядком аргументов Object.assign, все будет в порядке.

Ответ 14

Вы можете добавить это объявление, чтобы отключить предупреждения.

declare var obj: any;

Ответ 15

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

interface customObject extends MyObject {
   newProp: string;
   newProp2: number;
}

Ответ 16

Самое простое будет следующее

const obj = <any>{};
obj.prop1 = "value";
obj.prop2 = "another value"

Ответ 17

Вы можете использовать это:

this.model = Object.assign(this.model, { newProp: 0 });

Ответ 18

Чтобы сохранить предыдущий тип, временно создайте свой объект для любого

  var obj = {}
  (<any>obj).prop = 5;

Новое динамическое свойство будет доступно только при использовании трансляции:

  var a = obj.prop; ==> Will generate a compiler error
  var b = (<any>obj).prop; ==> Will assign 5 to b with no error;

Ответ 19

динамически назначать свойства объекту в TypeScript.

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

interface IValue {
    prop1: string;
    prop2: string;
}

interface IType {
    [code: string]: IValue;
}

Вы можете использовать это так

var obj: IType = {};
obj['code1'] = { 
    prop1: 'prop 1 value', 
    prop2: 'prop 2 value' 
};

Ответ 20

Если вы используете Typescript, вероятно, вы хотите использовать тип безопасности; в этом случае голый объект и "любой" противопоказаны.

Лучше не использовать Object или {}, а какой-нибудь именованный тип; или вы можете использовать API с определенными типами, которые вам нужно расширить своими собственными полями. Я нашел это, чтобы работать:

class Given { ... }  // API specified fields; or maybe it just Object {}

interface PropAble extends Given {
    props?: string;  // you can cast any Given to this and set .props
    // '?' indicates that the field is optional
}
let g:Given = getTheGivenObject();
(g as PropAble).props = "value for my new field";

// to avoid constantly casting: 
let k:PropAble = getTheGivenObject();
k.props = "value for props";

Ответ 21

Попробуйте это:

export interface QueryParams {
    page?: number,
    limit?: number,
    name?: string,
    sort?: string,
    direction?: string
}

Тогда используйте это

const query = {
    name: 'abc'
}
query.page = 1

Ответ 22

Если вы можете использовать функции ES6 JavaScript, вы можете использовать Имена вычисляемых свойств, чтобы справиться с этим очень легко:

var req = {id : 0123456};    
var response = {responses: {[req.id]: 'The 0123456 response message'}};

Ключ объекта [req.id] имеет динамическое значение