Как динамически назначить свойства объекту в TypeScript?
-
13-12-2019 - |
Вопрос
Если бы я хотел программно присвоить свойство объекту в Javascript, я бы сделал это следующим образом:
var obj = {};
obj.prop = "value";
Но в TypeScript это генерирует ошибку:
Свойство «prop» не существует для значения типа «{}».
Как мне присвоить какое-либо новое свойство объекту в TypeScript?
Решение
Можно обозначить obj
в виде any
, но это поражает всему целую цель использования Tymdercript.Генеракодицетагкод подразумевает генеракодицетагкод - генеракодицетагкод.Маркировка его как генеракодицетагкод не имеет смысла.Для достижения желаемой согласованности интерфейс может быть определен следующим образом.
interface LooseObject {
[key: string]: any
}
var obj: LooseObject = {};
.
или сделать его компактным:
var obj: {[k: string]: any} = {};
.
obj = {}
может принимать поля с любой строкой в качестве ключа и типа obj
в качестве значения.
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
с другой стороны, т.е. 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";
.
Вы можете создать новый объект на основе старого объекта, используя оператор по распространению
interface MyObject {
prop1: string;
}
const myObj: MyObject = {
prop1: 'foo',
}
const newObj = {
...myObj,
prop2: 'bar',
}
console.log(newObj.prop2); // 'bar'
.
TypeScript выводится, все поля исходного объекта и VSCode будут делать автозаполнение и т. Д.
Проще всего будет следовать
const obj = <any>{};
obj.prop1 = "value";
obj.prop2 = "another value"
. Чтобы гарантировать, что тип является Object
(т.е. пары ключ-значение), использовать:
const obj: {[x: string]: any} = {}
obj.prop = 'cool beans'
Можно добавить элемент в существующий объект
- Расширение типа (прочитайте: продлить / специализируйтесь на интерфейс)
- отбрасывает оригинальный объект к расширенному типу
- Добавить участника на объект
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();
.JavaScript:
myObj.myProperty = 1;
.
Типссы:
myObj['myProperty'] = 1;
. Храните любую новое свойство на любом объекте, написав его на «любой»:
var extend = <any>myObject;
extend.NewProperty = anotherObject;
.
Позже вы можете получить его, путем вытягивания расширенного объекта обратно на «любой»:
var extendedObject = <any>myObject;
var anotherObject = <AnotherObjectType>extendedObject.NewProperty;
. - .
-
case 1:
var car = {type: "BMW", model: "i8", color: "white"}; car['owner'] = "ibrahim"; // You can add a property:
-
case 2:
var car:any = {type: "BMW", model: "i8", color: "white"}; car.owner = "ibrahim"; // You can set a property: use any type
Я удивлен, что ни один из ответов, ссылочных объектов.assign с тех пор, как это технику, которую я использую всякий раз, когда я думаю о «составе» в JavaScript.
И это работает как ожидалось в Teadercript:
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
вообще - использует агрегатный тип типографии (как обозначается генеракодицетагкодом при объявлении типа
&
), который явно связывает, что мы составляем новый тип на лету (I.E. динамически)
<Сильные> вещи, которые нужно знать
- Object.Assign имеет свои уникальные аспекты (которые хорошо известны большинству опытных devs js), которые следует учитывать при написании Teadercript.
- .
- его можно использовать в смежной моде или неизменному способу (я демонстрирую неизменяемый путь выше, что означает, что генеракодицетагкод остается нетронутым и, следовательно, не имеет свойства
objectWithAllProps
. Для большинства функциональных программистов стилей, это хорошо вещь, поскольку результат - единственное новое изменение).
- его можно использовать в смежной моде или неизменному способу (я демонстрирую неизменяемый путь выше, что означает, что генеракодицетагкод остается нетронутым и, следовательно, не имеет свойства
- Object.Assign работает лучше всего, когда у вас есть льденные объекты. Если вы объединяете два вложенных объекта, которые содержат ненужные свойства, вы можете в конечном итоге перезаписать правдивые значения с undefined. Если вы следите за порядком аргументов Object.assign, вы должны быть в порядке.
Вы можете добавить эту декларацию, чтобы заставить замолчать предупреждения.
declare var obj: any;
Лучшая практика используется безопасная набравка, рекомендую вам:
interface customObject extends MyObject {
newProp: string;
newProp2: number;
}
. Вы можете использовать это:
this.model = Object.assign(this.model, { newProp: 0 });
. Чтобы сохранить ваш предыдущий тип, временный отставьте свой объект на любой
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;
. Если вы используете TypeScript, предположительно вы хотите использовать безопасность типа;в этом случае голый объект и «любой» встречаются.
Лучше не использовать объект или {}, но какой-то названный тип;Или вы можете использовать API с определенными типами, которые вам нужно продлить свои собственные поля.Я нашел это, чтобы работать:
class Given { ... } // API specified fields; or maybe it's 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";
.
Для этого вам просто нужно использовать интерфейсы TeampScript, которые так:
interface IValue {
prop1: string;
prop2: string;
}
interface IType {
[code: string]: IValue;
}
.
Вы можете использовать это так, как
var obj: IType = {};
obj['code1'] = {
prop1: 'prop 1 value',
prop2: 'prop 2 value'
};
. Попробуйте:
export interface QueryParams {
page?: number,
limit?: number,
name?: string,
sort?: string,
direction?: string
}
.
Тогда используйте его
const query = {
name: 'abc'
}
query.page = 1
. Если вы можете использовать функции es6 javascript, вы можете использовать вычисляемые имена свойств для обработки это очень легко:
var req = {id : 0123456};
var response = {responses: {[req.id]: 'The 0123456 response message'}};
.
Клавиша объекта [req.id] имеет динамическое значение