Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 | 41x 5x 36x 35x 34x 33x 7x 7x 1x 6x 26x 5x 21x 6x 6x 3x 1x 15x 2x 13x 6x 7x 4x 3x 3x 3x 18x 13x 13x 12x 11x 10x 2x 8x 2x 6x 4x 2x | import { SpelEvaluationException } from '../error/spel-evaluation-exception.js';
import { SpelMessage } from '../error/spel-message.js';
/**
* Parallels Spring TypeConverter / SpelTypeConverter
*
* Type coercion, handles implicit type conversion in SpEL.
*/
export class SpelTypeConverter {
/**
* Try converting value to target type
*/
public convertValue(value: unknown, targetType: new (...args: unknown[]) => unknown): unknown {
// null → null (any type)
if (value === null || value === undefined) {
return null;
}
// Already matching type
if (typeof value === 'string' && targetType === String) return value;
if (typeof value === 'number' && targetType === Number) return value;
if (typeof value === 'boolean' && targetType === Boolean) return value;
// String → Number
if (typeof value === 'string' && targetType === Number) {
const num = parseFloat(value);
if (isNaN(num)) {
throw new SpelEvaluationException(-1, SpelMessage.TYPE_CONVERSION_ERROR, value, 'Number');
}
return num;
}
// Number → String
if (typeof value === 'number' && targetType === String) {
return String(value);
}
// String → Boolean
if (typeof value === 'string' && targetType === Boolean) {
const s = value.toLowerCase();
if (s === 'true') return true;
if (s === 'false') return false;
throw new SpelEvaluationException(-1, SpelMessage.TYPE_CONVERSION_ERROR, value, 'Boolean');
}
// Boolean → String
if (typeof value === 'boolean' && targetType === String) {
return String(value);
}
// Number → Boolean (non-zero is truthy)
if (typeof value === 'number' && targetType === Boolean) {
return value !== 0;
}
// Boolean → Number
if (typeof value === 'boolean' && targetType === Number) {
return value ? 1 : 0;
}
// Cannot convert — value must be object/function at this point
const typeLabel = typeof value;
const valueStr = typeLabel;
throw new SpelEvaluationException(
-1,
SpelMessage.TYPE_CONVERSION_ERROR,
`${valueStr} (${typeLabel})`,
targetType.name,
);
}
/**
* Check if conversion is possible
*/
public canConvert(value: unknown, targetType: new (...args: unknown[]) => unknown): boolean {
if (value === null || value === undefined) return true;
const valueType = typeof value;
if (valueType === 'string' && targetType === String) return true;
if (valueType === 'number' && targetType === Number) return true;
if (valueType === 'boolean' && targetType === Boolean) return true;
if (valueType === 'string' && (targetType === Number || targetType === Boolean)) {
return true;
}
if (valueType === 'number' && (targetType === String || targetType === Boolean)) {
return true;
}
if (valueType === 'boolean' && (targetType === String || targetType === Number)) {
return true;
}
return false;
}
}
|