Reputation: 467
Here is an object with several different key and value, and each props of value differ from each other, how to best describe this object using TypeScript? Especially the setValue
method, how to limit type of the creatureType
, prop
and value
?
const object = {
john: {
name: '',
age: 18
},
alien: {
height: 20,
power:100,
},
setValue(creatureType) {
const self = this
return function (prop) {
return function (value) {
self[creatureType][prop] = value
}
}
}
}
Upvotes: 2
Views: 98
Reputation: 328658
Your setValue()
method will need to be generic if you want it to place strong restrictions on which properties and values go with which, uh, "creature type". Because the type of the object
's setValue()
method will be dependent on the type of the other properties of object
, the compiler will give up trying to infer types for it; it's too circular for something that isn't a class
. Either you could manually annotate all the types, which would be annoying, or you could split object
into two pieces, say plainObject
holding just the data, and then merge in the setValue()
method which will be dependent on the type of plainObject
, like this:
const plainObject = {
john: { name: '', age: 18 },
alien: { height: 20, power: 100 }
}
type PlainObject = typeof plainObject;
const object = {
...plainObject,
setValue<K extends keyof PlainObject>(creatureType: K) {
const self: PlainObject = this;
return function <P extends keyof PlainObject[K]>(prop: P) {
return function (value: PlainObject[K][P]) {
self[creatureType][prop] = value;
}
}
}
}
And you can verify that the compiler behaves as you want:
object.setValue("john")("age")(19); // okay
object.setValue("alien")("height")("pretty tall"); // error!
// "pretty tall" isn't numeric --> ~~~~~~~~~~~~~
object.setValue("john")("power")(9000); // error!
// "power" is wrong --> ~~~~~~~
object.setValue("elaine")("name")("elaine"); // error!
// "elaine"? -> ~~~~~~~~
Okay, hope that helps; good luck!
Upvotes: 3