Untyped Declarations
An LLM trained mostly on Python and JavaScript writes DATA lv_x. and moves on,
because in those languages a variable does not need a declared type. ABAP accepts that line — and gives you
something you almost certainly did not want.
Detected as: llm-dynamic-typing · severity warning
Declaration without explicit type
What ABAP does with an untyped DATA
DATA lv_x. is legal. It does not mean "any type" — it is shorthand for
TYPE c LENGTH 1. A single character. Assign 42
to it and you keep the 4. Assign 'Hello'
and you keep the H. Nothing raises an exception; the value is simply truncated.
" What the AI wrote
DATA lv_total.
lv_total = 150.
WRITE lv_total. " prints 1 — not 150
" What it meant
DATA lv_total TYPE i.
lv_total = 150.
WRITE lv_total. " prints 150
This is the worst kind of bug: it compiles, it runs, and it produces a plausible wrong answer.
A truncated c LENGTH 1 total looks like a data problem, not a
declaration problem, so it is easy to spend an afternoon looking in the wrong place.
The same mistake with field symbols
FIELD-SYMBOLS <fs> TYPE any. is the field-symbol version. It is
occasionally the right tool — genuinely generic code does need it — but as a default it turns compile-time
errors into runtime ones, and the compiler can no longer help you.
" Generic: mistakes surface at runtime, if at all
FIELD-SYMBOLS <ls_row> TYPE any.
" Typed: the compiler checks every field access
FIELD-SYMBOLS <ls_row> TYPE ty_employee.
" Best where possible — inline, type inferred from the table
LOOP AT lt_employees ASSIGNING FIELD-SYMBOL(<ls_row>).
WRITE / <ls_row>-name.
ENDLOOP.
Inline declarations are not untyped
Worth being clear, because it looks similar: DATA(lv_x) = ... has no
TYPE either, and it is perfectly good ABAP. The difference is that the
type is inferred from the right-hand side at compile time, not left unspecified. Modern ABAP prefers it.
DATA(lv_count) = LINES( lt_employees ). " typed i, inferred
DATA(lv_name) = |Alice|. " typed string, inferred
DATA lv_bad. " c LENGTH 1 — almost never intended
So the rule is not "always write TYPE". It is "never leave the type to chance".
The one inference that surprises everyone: packed arithmetic
When the right-hand side is arithmetic on packed numbers (TYPE p), the
inferred type is not the operands' type. ABAP's rule for inline declarations is that a calculation type
p always declares p LENGTH 8 with
no decimal places, so the result is rounded to a whole number.
That is how SAP specifies it, not a quirk of this site, and SAP's own documentation recommends
CONV or an explicit declaration instead.
TYPES ty_amount TYPE p LENGTH 8 DECIMALS 2.
DATA lv_amount TYPE ty_amount VALUE '19.99'.
DATA(lv_total) = 3 * lv_amount. " p LENGTH 8 DECIMALS 0: 60
DATA(lv_exact) = CONV ty_amount( 3 * lv_amount ). " 59.97
How to fix it
- Give every
DATAan explicitTYPE, or use inlineDATA(...)so the type is inferred — except for arithmetic on packed numbers, where you should useCONV. - Pick the type deliberately:
ifor counters,p LENGTH n DECIMALS mfor money,stringfor genuinely variable text,char40and friends for fixed fields. - Prefer
TYPE REF TO <class>overTYPE REF TO object. - Reserve
TYPE anyfor code that is deliberately generic — and say why in a comment.
Or paste your AI-generated code into the AI Validator to have this checked automatically.