( validator: TType<I>, input: I, typesToConvert: $ReadOnlyArray<TType<T>>, conversionFunction: T => T, options?: ?ConvertObjectOptions, )
| 98 | +dontValidateInput?: ?boolean, |
| 99 | }; |
| 100 | function convertObject<T, I>( |
| 101 | validator: TType<I>, |
| 102 | input: I, |
| 103 | typesToConvert: $ReadOnlyArray<TType<T>>, |
| 104 | conversionFunction: T => T, |
| 105 | options?: ?ConvertObjectOptions, |
| 106 | ): I { |
| 107 | if (input === null || input === undefined) { |
| 108 | return input; |
| 109 | } |
| 110 | const dontValidateInput = options?.dontValidateInput; |
| 111 | |
| 112 | // While they should be the same runtime object, |
| 113 | // `tValidator` is `TType<T>` and `validator` is `TType<I>`. |
| 114 | // Having them have different types allows us to use `assertWithValidator` |
| 115 | // to change `input` flow type |
| 116 | const tValidator = typesToConvert[typesToConvert.indexOf(validator)]; |
| 117 | if (tValidator && tValidator.is(input)) { |
| 118 | const tInput = assertWithValidator(input, tValidator); |
| 119 | const converted = conversionFunction(tInput); |
| 120 | return assertWithValidator(converted, validator); |
| 121 | } |
| 122 | |
| 123 | if (validator.meta.kind === 'maybe' || validator.meta.kind === 'subtype') { |
| 124 | return convertObject( |
| 125 | validator.meta.type, |
| 126 | input, |
| 127 | typesToConvert, |
| 128 | conversionFunction, |
| 129 | options, |
| 130 | ); |
| 131 | } |
| 132 | if (validator.meta.kind === 'interface' && typeof input === 'object') { |
| 133 | const recastValidator: TInterface<typeof input> = (validator: any); |
| 134 | const result: { [string]: mixed } = {}; |
| 135 | for (const key in input) { |
| 136 | const innerValidator = recastValidator.meta.props[key]; |
| 137 | if (!innerValidator && recastValidator.meta.strict === false) { |
| 138 | result[key] = input[key]; |
| 139 | continue; |
| 140 | } |
| 141 | result[key] = convertObject( |
| 142 | innerValidator, |
| 143 | input[key], |
| 144 | typesToConvert, |
| 145 | conversionFunction, |
| 146 | options, |
| 147 | ); |
| 148 | } |
| 149 | if (dontValidateInput) { |
| 150 | return (result: any); |
| 151 | } else { |
| 152 | return assertWithValidator(result, recastValidator); |
| 153 | } |
| 154 | } |
| 155 | if (validator.meta.kind === 'union') { |
| 156 | for (const innerValidator of validator.meta.types) { |
| 157 | if (innerValidator.is(input)) { |
no test coverage detected