Если бы я хотел программно назначить свойство для объекта в Javascript, я бы сделал это следующим образом:
var obj = {};
obj.prop = "value";
Но в TypeScript это порождает ошибку:
Свойство 'prop' не существует при значении типа '{}'
Как мне назначить какое-либо новое свойство объекту в TypeScript?
Обозначение 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;
Или все за один раз:
var obj:any = {}
obj.prop = 5;
any
, чтобы использовать его? Просто становится лишним шумом в моем коде ..: /
Я склонен ставить 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 = {};
Это решение полезно, когда ваш объект имеет определенный тип. Например, при получении объекта другому источнику.
let user: User = new User();
(user as any).otherProperty = 'hello';
//user did not lose its type here.
Хотя компилятор жалуется, он все равно должен выводить его по мере необходимости. Однако это будет работать.
var s = {};
s['prop'] = true;
Еще один вариант: доступ к свойству в виде коллекции:
var obj = {};
obj['prop'] = "value";
Object.assign(obj, {prop: "value"})
из ES6 / ES2015 тоже работает.
Чтобы гарантировать, что тип представляет собой Object
(то есть пары ключ-значение), используйте:
const obj: {[x: string]: any} = {}
obj.prop = 'cool beans'
Лучшей практикой является использование безопасной печати, я рекомендую вам:
interface customObject extends MyObject {
newProp: string;
newProp2: number;
}
Сохраните любое новое свойство на любом объекте, указав его на "any":
var extend = <any>myObject;
extend.NewProperty = anotherObject;
Позже вы можете получить его, отбросив расширенный объект до "any":
var extendedObject = <any>myObject;
var anotherObject = <AnotherObjectType>extendedObject.NewProperty;
Вы можете добавить это объявление, чтобы отключить предупреждения.
declare var obj: any;
Можно добавить члена к существующему объекту
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();
Чтобы сохранить предыдущий тип, временно создайте свой объект для любого
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;
Случай 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
Если вы используете 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";
динамически назначать свойства объекту в 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'
};
attributes
внутри SomeClass
и это должно исправить его public attributes: IType = {};
pastebin.com/3xnu0TnN
Я удивлен, что ни один из ответов не ссылается на 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
тип вообще&
при объявлении типа objectWithAllProps
), что четко objectWithAllProps
, что мы создаем новый типЧто нужно знать
existingObject
объект остается неизменным и, следовательно, не имеет свойства email
. Для большинства программистов в функциональном стиле это хорошо, так как результат - единственное новое изменение).Если вы можете использовать функции ES6 JavaScript, вы можете использовать Имена вычисляемых свойств, чтобы справиться с этим очень легко:
var req = {id : 0123456};
var response = {responses: {[req.id]: 'The 0123456 response message'}};
Ключ объекта [req.id] имеет динамическое значение