Is it possible to make a field optional when the other field is of type X?
I want action.meta
to be never
when the payload
is an array, and when it's an object
make it { resourceId: string }
const ADD_RESOURCES = 'ADD_RESOURCES'
type Resource = { id: string }
type AddResource<R = any> = {
type: typeof ADD_RESOURCES
payload: R extends [] ? Resource[] : (Resource | null)
meta: R extends [] ? never : { // when payload is an array, make meta never
resourceId: string
}
}
const action: Resource = {
type: ADD_RESOURCES,
payload: [{ id: '1' }]
// allow me to omit meta when the payload is array
}
if (Array.isArray(action.payload)) {
action.meta // make action.meta never
} else {
action.meta // make action.meta { resourceId: string }
}
You are better off using a union in this case. Since you discriminate by the payload
property being an array or not, you can't really use the discriminated union pattern to narrow action
and you will need to use a custom type guard:
const ADD_RESOURCES = 'ADD_RESOURCES'
type Resource = { id: string }
type AddResource = {
type: typeof ADD_RESOURCES
payload: Resource | null,
meta: { // when payload is an array, make meta never
resourceId: string
}
} | {
type: typeof ADD_RESOURCES
payload: Resource[],
meta: never // you can just omit this.. or type it as undefined
}
const action: AddResource = {
type: ADD_RESOURCES,
payload: [{ id: '1' }]
} as AddResource // Assertion here so flow analasys doesn't just use the actual type of the object literal instead of AddResource
function isArrayResource(r: AddResource): r is Extract<AddResource, { payload: Resource[] }> {
return Array.isArray(action.payload);
}
if (isArrayResource(action)) {
action.meta // action.meta never
} else {
action.meta // action.meta { resourceId: string }
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.