TypeScript Troubles? We've Got Fixes!
Budget: $10 – $20 USD
sendRequest function should be as follows:
2 arguments:
1st - data
2nd - callback
Can't be a single argument as an object, because of backward compatibility reasons.
Typings for sendRequest:
See the additional info section for detailed information.
Data must be one value in the interface allRequests. It cannot be more than one, or less than one. For example:
type req_getInfo = sendReqType<["getInfo"], ["info"]>;
// data must have getInfo key from Proto.AppRequest, and nothing else
// returns info key from Proto.appResponse in callback
type req_setEntityValue = sendReqType<
["setEntityValue", "entityId"],
["success"]
>;
// Similar to the getInfo request, but this time the data object must have both setEntityValue from Proto.AppResponse and entityId from Proto.AppResponse
let data = { getInfo: {}} // should be valid, callback should be info from Proto.AppResponse
data = { setEntityValue: {value: true}, entityId: 12345} // should be valid callback is success from Proto.AppResponse
data = {getInfo:{}, setEntityValue: {value: true}, entityId: 12345} // should be invalid, too many keys, doesn't match any known types
See playground link lines 149 - 167 on specific examples in context
Playground: https://tsplay.dev/m3Kl3m
So I have this function sendRequest(data, callback?)
Playground class on line 149
the value that we call in callback is based on the data argument. We know each possible value ahead of time, thanks to manual testing and the auto-generated proto.ts file.
What to know about sendRequest:
data is an object with what to request from the server
e.g: {getTime: {}} or {setEntityValue: {value:true}, entityId: 12345}
if any error occurred the server returns {response: {error: AppError}}
Non error response:
getTime: {response: {time: AppTime}}
setEntityValue: {response: {success: AppSuccess}}
I made a helper type to try to generate this: sendReqType<T,U>
T is an array of keys to data args e.g. ['setEntityValue','entityId']
U is an array of keys to values in callback arg e.g. ['success']
I made sendReqType for each possible key based on manual testing on returned types from server.
Then I made an allRequests interface:
interface allRequests {
getTime: req_getTime;
setEntityValue: req_setEntityValue;
// ...others
}
Current implementation:
sendRequest<T extends keyof allRequests>(
data: allRequests[T]["data"],
callback?: (message: {
response: allRequests[T]["response"];
}) => Promisable<void> | boolean
) {
// do stuff
}
This does work correctly if I pass in the generic. Example:
sendRequest<'getTime'>({getTIme:{}}, m=>m.response.error||m.response.success)
But otherwise the callback arg seems to be all possible values, rather than just the one matching the key.
sendRequest({getTIme:{}, setEntityValue:{value:true}}, m=>m.response.error||m.response.success) // no error in arg1
// m is union of allRequests[keyof allRequests] basically
// error w/ callback: success does not exist on type {error: undefined, time: AppTime} ... and 9 others
I need some way of getting this to work without passing in a key for the generic every time.
2 arguments:
1st - data
2nd - callback
Can't be a single argument as an object, because of backward compatibility reasons.
Typings for sendRequest:
See the additional info section for detailed information.
Data must be one value in the interface allRequests. It cannot be more than one, or less than one. For example:
type req_getInfo = sendReqType<["getInfo"], ["info"]>;
// data must have getInfo key from Proto.AppRequest, and nothing else
// returns info key from Proto.appResponse in callback
type req_setEntityValue = sendReqType<
["setEntityValue", "entityId"],
["success"]
>;
// Similar to the getInfo request, but this time the data object must have both setEntityValue from Proto.AppResponse and entityId from Proto.AppResponse
let data = { getInfo: {}} // should be valid, callback should be info from Proto.AppResponse
data = { setEntityValue: {value: true}, entityId: 12345} // should be valid callback is success from Proto.AppResponse
data = {getInfo:{}, setEntityValue: {value: true}, entityId: 12345} // should be invalid, too many keys, doesn't match any known types
See playground link lines 149 - 167 on specific examples in context
Playground: https://tsplay.dev/m3Kl3m
So I have this function sendRequest(data, callback?)
Playground class on line 149
the value that we call in callback is based on the data argument. We know each possible value ahead of time, thanks to manual testing and the auto-generated proto.ts file.
What to know about sendRequest:
data is an object with what to request from the server
e.g: {getTime: {}} or {setEntityValue: {value:true}, entityId: 12345}
if any error occurred the server returns {response: {error: AppError}}
Non error response:
getTime: {response: {time: AppTime}}
setEntityValue: {response: {success: AppSuccess}}
I made a helper type to try to generate this: sendReqType<T,U>
T is an array of keys to data args e.g. ['setEntityValue','entityId']
U is an array of keys to values in callback arg e.g. ['success']
I made sendReqType for each possible key based on manual testing on returned types from server.
Then I made an allRequests interface:
interface allRequests {
getTime: req_getTime;
setEntityValue: req_setEntityValue;
// ...others
}
Current implementation:
sendRequest<T extends keyof allRequests>(
data: allRequests[T]["data"],
callback?: (message: {
response: allRequests[T]["response"];
}) => Promisable<void> | boolean
) {
// do stuff
}
This does work correctly if I pass in the generic. Example:
sendRequest<'getTime'>({getTIme:{}}, m=>m.response.error||m.response.success)
But otherwise the callback arg seems to be all possible values, rather than just the one matching the key.
sendRequest({getTIme:{}, setEntityValue:{value:true}}, m=>m.response.error||m.response.success) // no error in arg1
// m is union of allRequests[keyof allRequests] basically
// error w/ callback: success does not exist on type {error: undefined, time: AppTime} ... and 9 others
I need some way of getting this to work without passing in a key for the generic every time.