Say I am returned some random object data. Now I wish validate and cast it to the appropiate type for use in the rest of my application. To do this I wrote the following utilty function.
static convertSingleSafe<T: (number | boolean | string | void)>(
data: {[string]: mixed},
name: string,
type: 'number' | 'boolean' | 'string' | 'object' | 'undefined'): T {
if (typeof data[name] === type ) {
return data[name]
} else {
throw new KeyError(`Badly formated value ${name}`, '')
}
}
Which would be called like:
const data: {[string]: mixed} = {val: 10, otherdata: 'test'};
//data would come from IE JSON.parse() of a request to server.
const val: number = convertSingleSafe<number>(data, 'val', 'number');
const msg: string = convertSingleSafe<string>(data, 'otherdata', 'string);
The problem, however, with this is that flow doesn't seem to understand the assertions in the convertSingleSafe function. On return data[name] the following error is shown:
Error:(82, 20) Cannot return
data[name]because: Either mixed [1] is incompatible with number [2]. Or mixed [1] is incompatible with boolean [3]. Or mixed [1] is incompatible with string [4].
Even though I quite explicitly test the value for that specific.
The other option, to let the generic be part of the data type gives the following error:
static convertSingleSafe<T: (number | boolean | string | void)>(
data: {[string]: T},
name: string,
type: 'number' | 'boolean' | 'string' | 'object' | 'undefined'): T
Error:(191, 41) Cannot call
FlowTest.convertSingleSafewithdbound todatabecause in the indexer property: Either mixed [1] is incompatible with number [2]. Or mixed [1] is incompatible with boolean [3]. Or mixed [1] is incompatible with string [4].
So (how) can I do this, without going through any casts?