Index signatures
It is possible to denote obj as any, but that defeats the whole purpose of using typescript. obj = {} implies obj is an Object. Marking it as any makes no sense. To accomplish the desired consistency an interface could be defined as follows, using an index signature
interface LooseObject {
[key: string]: any
}
var obj: LooseObject = {};
OR to make it compact:
var obj: {[k: string]: any} = {};
LooseObject can accept fields with any string as key and any type as value.
obj.prop = "value";
obj.prop2 = 88;
The real elegance of this solution is that you can include typesafe fields in the interface.
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;
Record<Keys,Type> utility type
Update (August 2020): @transang brought up the Record<Keys,Type> utility type in comments
Record<Keys,Type>is a Utility type in typescript. It is a much cleaner alternative for key-value pairs where property-names are not known. It's worth noting thatRecord<Keys,Type>is a named alias to{[k: Keys]: Type}whereKeysandTypeare generics. IMO, this makes it worth mentioning here
For comparison,
var obj: {[k: string]: any} = {};
becomes
var obj: Record<string,any> = {}
MyType can now be defined by extending Record type
interface MyType extends Record<string,any> {
typesafeProp1?: number,
requiredProp1: string,
}
While this answers the Original question, the answer here by @GreeneCreations might give another perspective on how to approach the problem.
Answer from Akash on Stack OverflowDynamic object keys in TypeScript
node.js - How to dynamically set an object key in typescript - Stack Overflow
How to set an an object with a dynamic key as React state in Typescript
Can I dynamically set the key of object using typescript? - Stack Overflow
Index signatures
It is possible to denote obj as any, but that defeats the whole purpose of using typescript. obj = {} implies obj is an Object. Marking it as any makes no sense. To accomplish the desired consistency an interface could be defined as follows, using an index signature
interface LooseObject {
[key: string]: any
}
var obj: LooseObject = {};
OR to make it compact:
var obj: {[k: string]: any} = {};
LooseObject can accept fields with any string as key and any type as value.
obj.prop = "value";
obj.prop2 = 88;
The real elegance of this solution is that you can include typesafe fields in the interface.
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;
Record<Keys,Type> utility type
Update (August 2020): @transang brought up the Record<Keys,Type> utility type in comments
Record<Keys,Type>is a Utility type in typescript. It is a much cleaner alternative for key-value pairs where property-names are not known. It's worth noting thatRecord<Keys,Type>is a named alias to{[k: Keys]: Type}whereKeysandTypeare generics. IMO, this makes it worth mentioning here
For comparison,
var obj: {[k: string]: any} = {};
becomes
var obj: Record<string,any> = {}
MyType can now be defined by extending Record type
interface MyType extends Record<string,any> {
typesafeProp1?: number,
requiredProp1: string,
}
While this answers the Original question, the answer here by @GreeneCreations might give another perspective on how to approach the problem.
This solution is useful when your object has Specific Type. Like when obtaining the object to other source.
let user: User = new User();
(user as any).otherProperty = 'hello';
//user did not lose its type here.
I've been able to find a way out using the code snippet below
export const validateObjectId = (key: string = 'id'): ObjectSchema => {
interface Obj {
[key: string]: Object;
}
const object: Obj = {};
object[key] = Joi.string()
.regex(/^(?=[a-f\d]{24}$)(\d+[a-f]|[a-f]+\d)/i)
.required();
return Joi.object(object);
};
Maybe you can try the following:
export const validateObjectId = (key: string = 'id'): ObjectSchema => {
let object: any = {};
object[key] = Joi.string()
.regex(/^(?=[a-f\d]{24}$)(\d+[a-f]|[a-f]+\d)/i)
.required();
return Joi.object(object);
}
Cheers
Replace
[field: string]: {
property1: string,
property2: string
}
by
interface Anything {
[key: string]: any;
}
And when you're calling then: do this
let item = { property1: "randomTest", property2: "randomTest1", property3: "randomTest3"}
this.setState({
[item].property1: "test value 1"
})
Add a semecon before testKey1: string;