Having some trouble trying to get the type to work correctly here.
I want to specify in an object that each top-level key is one of the strings from a union, and the value is a nested object that has keys of one of the strings from another union, and its value can be the string from the first union (kind of like a state-machine).
Eg:
type Status = 'idle' | 'loading' | 'error' | 'view'
type Actions = 'search' | 'search_success' | 'search_failure'
const app = {
idle: {
search: 'loading'
},
loading: {
search_success: 'view',
search_fail: 'error',
},
error: {
search: 'loading'
}
view: {
search: 'loading'
}
}
My attempts to type this have been:
type States = { [key in Status]: { [key in Actions]: Status } };
Though this doesn't work. Could somebody explain how I could make use of some utility types possibly to allow the nested object key to not require ALL values from the Actions type?
Thanks!
I simplified your code a bit.
This definition
type Status = 'idle' | 'loading'
type State = { [key in Status]: any}
is equivalent to
type State = {
idle: any;
loading: any;
}
Therefor, the following code is invalid
const foo: State = {
idle: true
}
because it's missing the prop loading.
A solution - make the props optional
type Status = 'idle' | 'loading' | 'error' | 'view'
type Actions = 'search' | 'search_success' | 'search_failure'
type States = { [key in Status]?: { [key in Actions]?: Status } };
const app: States = {
idle: {
search: 'loading'
},
loading: {
search_success: 'view',
search_failure: 'error',
},
error: {
search: 'loading'
},
view: {
search: 'loading'
}
}
playground
The answer from @MoshFeu looks like it'll work fine, but as I've written this up, I'll post it to say that you can get more or less the same thing with a Partial:
type Status = 'idle' | 'loading' | 'error' | 'view'
type Actions = 'search' | 'search_success' | 'search_failure'
type States = { [key in Status]: Partial<{ [key in Actions]: Status }> };
const app: States = {
idle: {
search: 'loading'
},
loading: {
search_success: 'view',
search_failure: 'error',
},
error: {
search: 'loading'
},
view: {
search: 'loading'
}
};
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With