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