[{"data":1,"prerenderedAt":132},["ShallowReactive",2],{"entry-\u002Fblog\u002Ftypescript-into-a-sapui5-codebase-en":3},{"entry":4,"writtenIn":131,"onlyIn":123},{"id":5,"title":6,"body":7,"date":117,"description":118,"extension":119,"meta":120,"navigation":121,"path":122,"role":123,"seo":124,"stack":125,"stem":126,"tags":127,"year":123,"__hash__":130},"content_en\u002Fblog\u002Ftypescript-into-a-sapui5-codebase.md","TypeScript into a SAPUI5 codebase",{"type":8,"value":9,"toc":111},"minimark",[10,14,19,22,70,73,76,80,87,90,94,97,104,107],[11,12,13],"p",{},"SAPUI5 predates the assumption that a frontend codebase is typed. Its module system, its class definitions, and its XML views were all designed for a world where the editor could not help you. Types can be added, but not evenly — some parts of the framework reward them immediately, and some resist.",[15,16,18],"h2",{"id":17},"where-it-pays-immediately","Where it pays immediately",[11,20,21],{},"Model access is the clearest win. A line like this is where most of the runtime bugs live:",[23,24,29],"pre",{"className":25,"code":26,"language":27,"meta":28,"style":28},"language-ts shiki shiki-themes henricus","const rate = model.getProperty(\"\u002Fheader\u002FexchangeRate\");\n","ts","",[30,31,32],"code",{"__ignoreMap":28},[33,34,37,41,45,48,51,55,58,61,65,67],"span",{"class":35,"line":36},"line",1,[33,38,40],{"class":39},"s5glF","const",[33,42,44],{"class":43},"s6eg1"," rate ",[33,46,47],{"class":39},"=",[33,49,50],{"class":43}," model.",[33,52,54],{"class":53},"sNWak","getProperty",[33,56,57],{"class":43},"(",[33,59,60],{"class":43},"\"",[33,62,64],{"class":63},"s3_7c","\u002Fheader\u002FexchangeRate",[33,66,60],{"class":43},[33,68,69],{"class":43},");\n",[11,71,72],{},"Everything about it is a guess: whether the path exists, whether it is a number, whether it can be null after a failed load. Typing the model shape moves all three guesses into the editor.",[11,74,75],{},"Formatters and OData calls follow. Both are boundaries — data crosses them and changes shape — and boundaries are exactly where a type is worth the keystrokes.",[15,77,79],{"id":78},"where-it-turns-into-ceremony","Where it turns into ceremony",[11,81,82,83,86],{},"Controller lifecycle methods gain almost nothing. ",[30,84,85],{},"onInit"," takes no arguments and returns nothing; typing it is filling in a form.",[11,88,89],{},"XML views are the real limit. A view binds to a controller method by string name, and no compiler checks that string. You can type the controller perfectly and still ship a view that calls a method deleted three commits ago. Types give a strong impression of safety across a gap they never cross.",[15,91,93],{"id":92},"what-i-would-tell-myself-at-the-start","What I would tell myself at the start",[11,95,96],{},"Type the data, not the framework. Model shapes, service responses, formatter inputs and outputs — those catch real defects.",[11,98,99,100,103],{},"Resist typing the parts that exist only to satisfy the framework. Every ",[30,101,102],{},"any"," you eliminate there costs a maintenance burden and returns nothing, and it makes the diff long enough that reviewers skim it.",[11,105,106],{},"The goal was never full coverage. It was knowing what shape the data is when it reaches the screen.",[108,109,110],"style",{},"html pre.shiki code .s5glF, html code.shiki .s5glF{--shiki-default:#E8D8A6}html pre.shiki code .s6eg1, html code.shiki .s6eg1{--shiki-default:#EDEBE3}html pre.shiki code .sNWak, html code.shiki .sNWak{--shiki-default:#C9A227}html pre.shiki code .s3_7c, html code.shiki .s3_7c{--shiki-default:#7BA697}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}",{"title":28,"searchDepth":112,"depth":112,"links":113},2,[114,115,116],{"id":17,"depth":112,"text":18},{"id":78,"depth":112,"text":79},{"id":92,"depth":112,"text":93},"2026-05-02","Adding types to a framework built before types were expected — where it pays off, and where it turns into ceremony.","md",{},true,"\u002Fblog\u002Ftypescript-into-a-sapui5-codebase",null,{"title":6,"description":118},[],"blog\u002Ftypescript-into-a-sapui5-codebase",[128,129],"sapui5","typescript","byv7yaXN7-Xfci9bH0WHPjdA5OfpNFwqdXWzty8ztB8","en",1788956392481]