如果我想以编程方式将属性分配给Javascript中的对象,我会这样做:
var obj = {};
obj.prop = "value";
但在TypeScript中,这会产生错误:
属性'prop'在类型'{}'
的值上不存在
我应该如何在TypeScript中为对象分配任何新属性?
答案 0 :(得分:253)
可以将obj
表示为any
,但这会破坏使用打字稿的整个目的。 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;
答案 1 :(得分:74)
或者一气呵成:
var obj:any = {}
obj.prop = 5;
答案 2 :(得分:50)
我倾向于将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 = {};
答案 3 :(得分:36)
当您的对象具有特定类型时,此解决方案很有用。就像将对象获取到其他来源时一样。
let user: User = new User();
(user as any).otherProperty = 'hello';
//user did not lose its type here.
答案 4 :(得分:31)
虽然编译器抱怨它仍然应该根据需要输出它。但是,这将有效。
var s = {};
s['prop'] = true;
答案 5 :(得分:21)
另一个选择是将该属性作为集合访问:
var obj = {};
obj['prop'] = "value";
&#13;
答案 6 :(得分:5)
可以通过
将成员添加到现有对象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();
答案 7 :(得分:4)
将任何类型的对象存储在任何类型的对象上,将其类型化为“any”:
var extend = <any>myObject;
extend.NewProperty = anotherObject;
稍后您可以通过将扩展对象强制转换回'any'来检索它:
var extendedObject = <any>myObject;
var anotherObject = <AnotherObjectType>extendedObject.NewProperty;
答案 8 :(得分:4)
情况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
答案 9 :(得分:4)
这里是Object.assign
的特殊版本,它会在每次属性更改时自动调整变量类型。无需其他变量,类型断言,显式类型或对象副本:
function assign<T, U>(target: T, source: U): asserts target is T & U {
Object.assign(target, source)
}
const obj = {};
assign(obj, { prop1: "foo" })
// const obj now has type { prop1: string; }
obj.prop1 // string
assign(obj, { prop2: 42 })
// const obj now has type { prop1: string; prop2: number; }
obj.prop2 // number
// const obj: { prop1: "foo", prop2: 42 }
注意:sample使用TS 3.7 assertion functions。与assign
不同,void
的返回类型为Object.assign
。
答案 10 :(得分:4)
要确保该类型为Object
(即键值对),请使用:
const obj: {[x: string]: any} = {}
obj.prop = 'cool beans'
答案 11 :(得分:3)
您可以使用传播运算符基于旧对象创建新对象
interface MyObject {
prop1: string;
}
const myObj: MyObject = {
prop1: 'foo',
}
const newObj = {
...myObj,
prop2: 'bar',
}
console.log(newObj.prop2); // 'bar'
TypeScript会推断出原始对象的所有字段,而VSCode会进行自动补全,等等。
答案 12 :(得分:3)
Javascript:
myObj.myProperty = 1;
打字稿:
myObj['myProperty'] = 1;
答案 13 :(得分:3)
最佳做法是使用安全打字,我建议你:
interface customObject extends MyObject {
newProp: string;
newProp2: number;
}
答案 14 :(得分:3)
您可以添加此声明以使警告静音。
declare var obj: any;
答案 15 :(得分:2)
要保留以前的类型,请将对象临时转换为任何
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;
答案 16 :(得分:2)
我很惊讶没有答案引用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
类型&
的类型时用objectWithAllProps
表示),这清楚地表明我们正在动态(即动态地)构建新类型< / li>
注意事项
existingObject
保持不变,因此没有email
属性。对于大多数函数式程序员,这是一件好事,因为结果是唯一的新变化。答案 17 :(得分:1)
唯一具有类型安全性的解决方案是this one,但解决方案比较冗长,会迫使您创建多个对象。
如果您 必须 首先创建一个空对象,然后选择这两种解决方案之一。请记住,每次使用as
都会失去安全性。
object
中getObject
的类型为安全,这意味着object.a
的类型为string | undefined
interface Example {
a: string;
b: number;
}
function getObject() {
const object: Partial<Example> = {};
object.a = 'one';
object.b = 1;
return object as Example;
}
在object
内getObject
的类型是不安全,这意味着object.a
的类型将是string
,即使在分配之前。 / p>
interface Example {
a: string;
b: number;
}
function getObject() {
const object = {} as Example;
object.a = 'one';
object.b = 1;
return object;
}
答案 18 :(得分:1)
尝试一下:
export interface QueryParams {
page?: number,
limit?: number,
name?: string,
sort?: string,
direction?: string
}
然后使用它
const query = {
name: 'abc'
}
query.page = 1
答案 19 :(得分:1)
如果您正在使用Typescript,可能您想要使用类型安全;在这种情况下裸体对象和任何&#39;是反对的。
最好不要使用Object或{},而是使用一些命名类型;或者您可能正在使用具有特定类型的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";
答案 20 :(得分:1)
最简单的将是
const obj = <any>{};
obj.prop1 = "value";
obj.prop2 = "another value"
答案 21 :(得分:1)
在TypeScript中为对象动态分配属性。
要做到这一点你只需要使用这样的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'
};
答案 22 :(得分:0)
您可以使用:
this.model = Object.assign(this.model, { newProp: 0 });
答案 23 :(得分:0)
扩展Angular的@jmvtrinidad解决方案,
使用现有的类型化对象时,这是添加新属性的方法。
let user: User = new User();
(user as any).otherProperty = 'hello';
//user did not lose its type here.
现在,如果您想在HTML端使用otherProperty
,这就是您需要的:
<div *ngIf="$any(user).otherProperty">
...
...
</div>
当使用$any()
或any
强制转换时,Angular编译器将<any>
视作对as any
类型的强制转换。
答案 24 :(得分:-2)
如果您能够使用ES6 JavaScript功能,则可以使用Computed Property Names轻松处理此问题:
var req = {id : 0123456};
var response = {responses: {[req.id]: 'The 0123456 response message'}};
[req.id]对象键具有动态值