TypeScript and SharePoint - definition files
/
One of TypeScript's strengths is that you can use the ability to define Interfaces to produce Type Definition files for JavaScript. These interface definitions provides an IDE (like Visual Studio) with a lot more type information at compile time regarding how to use a certain JavaScript object.
A large repository of definition files are at: https://github.com/borisyankov/DefinitelyTyped
Why is this related to SharePoint? Well, javascript files provided in SharePoint are actually quite rich in meta data and could potentially be used to reverse engineer the TypeScript Definition Files.
Without further delay...
- Here's my TypeScript program
- which will generate a JavaScript program
- which will parse and read SP's JavaScript objects
- which will produce TypeScript definition results
TypeScript code
module tools {
export function findReturnType(o: any): string {
// return;
if (/return\s*;/gi.test(o)) return ": void";
// no return
if (!/return/gi.test(o)) return ": void";
// return 1.1; return 1;
if (/return\s*\d+(\.\d+)?;/gi.test(o)) return ": number";
// return "xx";
if (/return\s*"[^"]*?"\s*;/gi.test(o)) return ": string";
// return 'xx';
if (/return\s*'[^']*?'\s*;/gi.test(o)) return ": string";
// return something;
if (/return\s*[^;]+?;/gi.test(o)) return ": any";
// don't know
return ": any";
}
export function toClass(o: any): string {
var isClass = o["__class"] == true;
var typeName = o["__typeName"];
var results = "interface " + typeName + "{\n";
for (var member in o) {
if (member.match(/\$|__/)) continue;
var m = o[member];
if (typeof (m) == "function") {
var match = /function\s*(\(.*?\))/gi.exec(m);
if (match) {
results += "function " + member + match[1] + findReturnType(m) + ";\n";
}
}
else {
results += "" + member + " : " + typeof (m) + ";\n";
}
}
results += "}\n";
return results;
}
export function toEnum(o: any): string {
var typeName = o["__typeName"];
var results = "interface " + typeName + "{\n";
for (var member in o) {
if (member.match(/\$|__/)) continue;
var m = o[member];
if (typeof (m) == "function") {
continue;
}
else {
results += "" + member + " : " + typeof (m) + ";\n";
}
}
results += "}\n";
return results;
}
export function toTypeScript(o: any): string {
var isClass = o["__class"] == true;
var isNamespace = o["__namespace"] == true;
var isEnum = o["__enum"] == true;
if (isClass) {
return toClass(o);
}
if (isEnum) {
return toEnum(o);
}
return "";
}
}
What does this do?
When you run this code in the SharePoint browser console, you'd get this:
Which is nearly a usable TypeScript definition file.
There are still a bunch of clean up to do, since this is a really basic list:
- You will need to clean up the interface name.
- If you want, improve the arguments list, a number of the arguments are actually optional.
- Remove zIndexStep and zIndexStart - which are properties in SP.UI.ModalDialog but aren't for public use.
- Remove bind function - that's from jQuery
Here's another example, with enum's defined in SP.UI
Summary
In this quick blog article, I talked about using a TypeScript program to read the javascript object, and infer TypeScript definitions. Since TypeScript contains far more information that isn't available in JavaScript, there will still be need to manually tweak the output.
Eventually, I hope we'll arrive at a place where we have fully documented TypeScript definitions for SharePoint available.
Charlie Holland has started such a work, and it is available on https://github.com/chaholl/TypeScriptDefinitions/