I'm having a weird problem with generic inferences, which is easier to explain in code then words (so apologies for the vague title).
I have a type for conveying the status of a data request:
enum Status {INIT, PENDING, LOADED, ERROR}
type StatusObject = {
status: Status,
initiated: boolean,
error: null | string
}
And then various data objects that include a property of this type, e.g.:
const obj1 = {
requestedData: "some data",
goodStatus: {
status: Status.LOADED,
initiated: true,
error: null
}
}
I have a function that will get passed an object like obj1 and the key name of the property of type StatusObject for further operations. Let's say:
function checkStatus<T extends string, U extends Record<T, StatusObject>>(
statusObjectKey: T,
theObject: U
)
In general, this type of signature works. For example, the following allows the first call but not the second as you'd hope:
const obj1 = {
requestedData: "some data",
goodStatus: {
status: Status.LOADED,
initiated: true,
error: null
}
}
const obj2 = {
data: "some other data",
badStatus: true
}
checkStatus("goodStatus", obj1). //no error
checkStatus("badStatus", obj2) //error, because obj2 doesn't have a badStatus property of type StatusObject
But inside the function itself things don't work as I'd expect. Namely--
function checkStatus<T extends string, U extends Record<T, StatusObject>>(
statusObjectKey: T,
theObject: U
) {
let testStatus: StatusObject
testStatus = theObject[statusObjectKey] // no error here
theObject[statusObjectKey] = testStatus // but an error here. WHY?
}
On the second assignment, I don't understand why TS can't tell that theObject[statusObjectKey] is of type ObjectStatus (but does seem to be able to tell it in the first assignment).
Can anyone help me understand this? Is there a better way to type this kind of function?
Here's the code in a playground.