-
Notifications
You must be signed in to change notification settings - Fork 13.1k
Description
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.