Making your own limited exporter should be pretty easy if you know how to loop each shape and vertex. Now I personally can not help you with Sketch or Affinity editor since I have neither. But this is quite trivial to do in illustrator.
On the other hand some tools like morphSVG will automatically fix these things for you. Though i do get that sometimes the exact control of having exactly the points you want is a godsend for controlling the details as you intended.
Side note: When I try this is illustrator then the codes are stable, however if you need to do hard to non-hard/smooth interpolation it wont work even here.
Image 1: Simple demo, click link for live in browser. Paths done with code below.
So here is a version that constantly uses C (absolute curve) between any path segment for illustrator to avoid problems with changing point types. It even uses bezier paths for straight segments. You can use this as a scaffold for developing your own.
// jooExportSVGScaffold.jsx
// run in extendscript toolkit or put in a file with .jsx
// extension and drag and drop on illustrator.
//
// files saves a a4 output with only curve to segments of paths so they
// always stay the same when exported so it can easily be interpolated
// later.
#target illustrator
main();
function ppos(point){
return ""+point[0]+" "+-1*point[1]
}
function handlePath(path) {
var out = "";
var pnts = path.pathPoints;
var ipos = pnts[0].anchor;
var pos = pnts[0].rightDirection;
var pos2, pos3;
out="M"+ppos(ipos);
for (var p=1; p<pnts.length; p++){
pos2 = pnts[p].leftDirection;
pos3 = pnts[p].anchor;
out += "C"+ppos(pos)+" "+ppos(pos2)+" "+ppos(pos3);
pos = pnts[p].rightDirection;
}
if (path.closed){
pos2 = pnts[0].leftDirection;
pos3 = pnts[0].anchor;
out += "C"+ppos(pos)+" "+ppos(pos2)+" "+ppos(pos3)+"Z";
}
return out;
}
function main() {
var sel = app.activeDocument.selection;
var file = File.saveDialog('save C curve SVG', 'SVGPath:*.svg');
file.open('w');
file.writeln('<?xml version="1.0" encoding="utf-8"?>');
file.writeln('<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">');
file.writeln('<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"');
file.writeln('width="595.28px" height="841.89px" viewBox="0 0 595.28 841.89" enable-background="new 0 0 595.28 841.89" xml:space="preserve">');
var doc = app.activeDocument;
var paths = doc.pathItems;
for (var i=0; i<paths.length; i++){
data=handlePath(paths[i]);
file.writeln('<path fill="none" stroke="black" d="'+data+'"/>');
}
file.writeln('</svg>');
file.close();
}
Here is a demo animation done with this method, path values taken from the exported SVG that was made with my script. This is effect is particularly hard for the default exporter to achieve.
PS: it is also possible to post correct a SVG into C only spans. Its a bit more complicated but not impossible to turn a S into a C and turn a L into a C etc.