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

610
84

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


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

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


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



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

спросил(а) 2012-10-03T17:42:00+04:00 8 лет назад
1
Решение
81

    Случай 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

ответил(а) 2019-01-12T18:45:00+03:00 1 год, 9 месяцев назад
624

Обозначение 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;

ответил(а) 2017-06-08T19:32:00+03:00 3 года, 4 месяца назад
343

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

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

ответил(а) 2012-10-03T18:51:00+04:00 8 лет назад
287

Я склонен ставить 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 = {};


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

ответил(а) 2013-08-26T15:32:00+04:00 7 лет, 2 месяца назад
245

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


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

ответил(а) 2016-08-25T11:51:00+03:00 4 года, 2 месяца назад
223

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


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

ответил(а) 2012-10-03T17:57:00+04:00 8 лет назад
186

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


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

ответил(а) 2017-03-22T16:23:00+03:00 3 года, 7 месяцев назад
92

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

расширение типа (читай: расширять/специализировать интерфейс) приведите исходный объект к расширенному типу добавить член к объекту
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();

ответил(а) 2018-03-08T14:20:00+03:00 2 года, 7 месяцев назад
91

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


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

ответил(а) 2017-06-16T17:15:00+03:00 3 года, 4 месяца назад
90

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


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

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


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

ответил(а) 2015-11-25T16:21:00+03:00 4 года, 11 месяцев назад
81

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


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

ответил(а) 2016-10-12T02:32:00+03:00 4 года назад
82

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


declare var obj: any;

ответил(а) 2012-10-03T18:02:00+04:00 8 лет назад
70

Javascript:

myObj.myProperty = 1;

Машинопись:

myObj['myProperty'] = 1;

ответил(а) 2019-02-09T12:43:00+03:00 1 год, 8 месяцев назад
70

Я удивлен, что ни один из ответов не ссылается на 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: "jsmith@someplace.com"
})

console.log(objectWithAllProps.email); // jsmith@someplace.com

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

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

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

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

ответил(а) 2019-01-30T19:21:00+03:00 1 год, 8 месяцев назад
70

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


  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;

ответил(а) 2016-12-09T19:44:00+03:00 3 года, 10 месяцев назад
58

Если вы используете 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";

ответил(а) 2018-01-02T06:07:00+03:00 2 года, 9 месяцев назад
59

динамически назначать свойства объекту в 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'
};

ответил(а) 2017-03-30T07:31:00+03:00 3 года, 7 месяцев назад
41

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

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

ответил(а) 2019-05-02T23:18:00+03:00 1 год, 5 месяцев назад
-6

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

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

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

ответил(а) 2018-01-16T14:03:00+03:00 2 года, 9 месяцев назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема