Last active
April 24, 2020 17:47
-
-
Save hipstersmoothie/1a3f5d068d31c8057c85a211944cc650 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const ts = require("typescript"); | |
const vfs = require("@typescript/vfs"); | |
const compilerOptions = { | |
strict: true, | |
target: ts.ScriptTarget.ES2015, | |
typeRoots: [], | |
lib: ["es5"], | |
skipDefaultLibCheck: true, | |
skipLibCheck: true, | |
moduleResolution: ts.ModuleResolutionKind.NodeJs, | |
module: ts.ModuleKind.ES2015, | |
}; | |
const filename = "index.ts"; | |
const file = ` | |
interface StackBaseProps<T> { | |
as: T; | |
hasWrap?: boolean; | |
} | |
interface StackJustifyProps { | |
/** The foo prop should not repeat the description */ | |
foo?: 'blue'; | |
/** You cannot use gap when using a "space" justify property */ | |
gap?: never; | |
} | |
interface StackGapProps { | |
/** The foo prop should not repeat the description */ | |
foo?: 'red'; | |
/** The space between children */ | |
gap?: number; | |
} | |
type StackProps<T = string> = StackBaseProps<T> & (StackGapProps | StackJustifyProps); | |
`; | |
async function run() { | |
const fsMap = await vfs.createDefaultMapFromNodeModules(compilerOptions); | |
fsMap.set(filename, file); | |
const system = vfs.createSystem(fsMap); | |
const host = vfs.createVirtualCompilerHost(system, compilerOptions, ts); | |
const program = ts.createProgram({ | |
rootNames: [...fsMap.keys()], | |
options: compilerOptions, | |
host: host.compilerHost, | |
}); | |
const checker = program.getTypeChecker(); | |
// This will update the fsMap with new files | |
// for the .d.ts and .js files | |
program.emit(); | |
// Now I can look at the AST for the .ts file too | |
const index = program.getSourceFile("index.ts"); | |
const properties = checker | |
.getDeclaredTypeOfSymbol(index.locals.get("StackProps")) | |
.getProperties(); | |
console.log( | |
properties.map((prop) => { | |
const propType = checker.getTypeOfSymbolAtLocation(prop, index); | |
const isOptional = (prop.getFlags() & ts.SymbolFlags.Optional) !== 0; | |
const description = Array.from( | |
new Set( | |
prop | |
.getDocumentationComment() | |
.map((d) => d.text.trim()) | |
.filter((t) => t !== "") | |
) | |
).join("\n"); | |
return { | |
name: prop.getName(), | |
type: checker.typeToString(propType), | |
// BUG: Required always returns true | |
required: !isOptional, | |
description, | |
}; | |
}) | |
); | |
} | |
run(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment