Answers:
可以将表示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;
虽然这回答了原始问题,但@GreeneCreations 在这里给出的答案可能会为如何解决该问题提供另一种观点。
LooseObject
也可以采取一个错误。
或一劳永逸:
var obj:any = {}
obj.prop = 5;
any
要使用很多类型的东西,TypeScript有什么意义?:/
any
。TypeScript用于在编译时捕获(潜在)错误。如果您强制转换any
为静音错误,那么您将失去打字的能力,并可能会回到纯JS。any
仅在导入无法编写TS定义的代码或在将代码从JS迁移到TS的同时才应理想地使用
我倾向于放在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 = {};
I still have <any>{
那么您还没有编译。TypeScript会删除其发出的内容
var foo: IFoo = {} as any
是首选。类型转换的旧语法与TSX(Typescript定义的JSX)相冲突。
当您的对象具有特定类型时,此解决方案很有用。就像在获取对象到其他来源时一样。
let user: User = new User();
(user as any).otherProperty = 'hello';
//user did not lose its type here.
我很惊讶没有答案引用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
),这清楚地表明我们正在动态(即动态)编写新类型要注意的事情
existingObject
保持不变,因此不具有email
属性。对于大多数函数式程序员而言,这是一件好事,因为结果是唯一的新变化)。最简单的将是
const obj = <any>{};
obj.prop1 = "value";
obj.prop2 = "another value"
可以通过以下方式将成员添加到现有对象
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();
由于您无法执行此操作:
obj.prop = 'value';
如果您的TS编译器和linter不严格,则可以这样编写:
obj['prop'] = 'value';
如果您的TS编译器或linter严格,则另一个答案是键入:
var obj = {};
obj = obj as unknown as { prop: string };
obj.prop = "value";
将任何新属性存储在任何类型的对象上,方法是将其类型转换为“ any”:
var extend = <any>myObject;
extend.NewProperty = anotherObject;
稍后,您可以通过将扩展对象转换回'any'来检索它:
var extendedObject = <any>myObject;
var anotherObject = <AnotherObjectType>extendedObject.NewProperty;
最佳做法是使用安全键入,我建议您:
interface customObject extends MyObject {
newProp: string;
newProp2: number;
}
为了保留您以前的类型,请将您的对象临时转换为任何类型
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;
这是的特殊版本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 }
如果您使用的是Typescript,则大概是要使用类型安全性。在这种情况下,会标明裸对象和“ any”。
最好不要使用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";
动态地为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'
};
唯一的完全类型安全的解决方案是this,但是有点罗word,并迫使您创建多个对象。
如果必须先创建一个空对象,则选择这两个解决方案之一。请记住,每次使用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
,甚至它的任务之前。
interface Example {
a: string;
b: number;
}
function getObject() {
const object = {} as Example;
object.a = 'one';
object.b = 1;
return object;
}