The idea is to instrument JavaScript code and collect types information from the runtime. For example:
Consider JavaScript code (in ES2015):
File render.js:
export function renderContact(contact, container) {
let span = document.createElement('span');
span.textContent = `${contact.firstName} ${contact.secondName}`;
container.appendChild(span);
}
Then we use it in file main.js:
import {renderContact} from "./render";
renderContact({firstName: "Steve", lastName: "Works"}, document.body);
Running this code as-is gives no help, but if it's instrumented then we may callect runtime information. main.js could be instrumented to the following form using esprima/escodegen or TypeScript's parser API:
import {renderContact} from "./render";
CallExpression({line:3, col:0},
null,
renderContact,
[{firstName: "Steve", lastName: "Works"}, document.body])
CallExpression body could roughly look like:
function CallExpression(position:Position, callee:any, fn:Function, args:any[) {
// collect types information part
args.forEach(arg=>CollectArgumentTypesInformation(position, arg));
// execution part to conform JavaScript semantics and do not break the running application code
return fn.apply(callee, args);
}
function CollectArgumentTypesInformation(position:Position, arg:any) {
let type={};
Object.keys(arg).forEach(key=>{
type[key]=typeof arg[key];
});
return type;
}
CollectArgumentTypesInformation for contact parameter would yield something like:
{
firstName:string,
lastName:string
}
that could be later transformed into interface contact (name of the interface is based on renderContact 1st parameter name):
interface contact {
firstName:string,
lastName:string
}
Later on this TypeScript type could be injected into the file like render.ts (next to the render.js) and then be used to generate d.ts file using TypeScript's tsc --declaration. Before running tsc --declaration author could refactor names for better naming and the instrumentation and types collection tool would respect that changes and wouldn't override them.
position would be used to source-map .js and .ts files. Or it could be something similar, maybe using sourceMaps project itself.
The idea is to instrument JavaScript code and collect types information from the runtime. For example:
Consider JavaScript code (in ES2015):
File
render.js:Then we use it in file
main.js:Running this code as-is gives no help, but if it's instrumented then we may callect runtime information.
main.jscould be instrumented to the following form using esprima/escodegen or TypeScript's parser API:CallExpressionbody could roughly look like:CollectArgumentTypesInformationforcontactparameter would yield something like:that could be later transformed into interface
contact(name of the interface is based onrenderContact1st parameter name):Later on this TypeScript type could be injected into the file like
render.ts(next to therender.js) and then be used to generated.tsfile using TypeScript'stsc --declaration. Before runningtsc --declarationauthor could refactor names for better naming and the instrumentation and types collection tool would respect that changes and wouldn't override them.positionwould be used to source-map.jsand.tsfiles. Or it could be something similar, maybe usingsourceMapsproject itself.