Created
June 18, 2020 21:55
-
-
Save dyerw/bec118a2a336cea46f620ed83af124a4 to your computer and use it in GitHub Desktop.
Play with generating TS Interfaces from Avro Schemas
This file contains 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
import * as ts from "typescript"; | |
// Haven't dealt with arrays and records | |
type AvscType = "string" | "int" | "null"; | |
type TsTypes = | |
| ts.SyntaxKind.StringKeyword | |
| ts.SyntaxKind.NumberKeyword | |
| ts.SyntaxKind.NullKeyword; | |
interface AvscField { | |
name: string; | |
type: AvscType | AvscType[]; | |
} | |
interface AvscRecord { | |
namespace: string; | |
name: string; | |
fields: AvscField[]; | |
} | |
const avscToTsTypeLookup: Record<AvscType, TsTypes> = { | |
["string"]: ts.SyntaxKind.StringKeyword, | |
["int"]: ts.SyntaxKind.NumberKeyword, | |
["null"]: ts.SyntaxKind.NullKeyword, | |
}; | |
function convertAvscFieldToTsPropertySignature( | |
avscField: AvscField | |
): ts.PropertySignature { | |
const propertyName = ts.createIdentifier(avscField.name); | |
if (typeof avscField.type === "string") { | |
const type = ts.createKeywordTypeNode(avscToTsTypeLookup[avscField.type]); | |
return ts.createPropertySignature( | |
undefined, | |
propertyName, | |
undefined, | |
type, | |
undefined | |
); | |
} | |
if (avscField.type instanceof Array) { | |
const types = avscField.type.map((t) => | |
ts.createKeywordTypeNode(avscToTsTypeLookup[t]) | |
); | |
const type = ts.createUnionTypeNode(types); | |
return ts.createPropertySignature( | |
undefined, | |
propertyName, | |
undefined, | |
type, | |
undefined | |
); | |
} | |
throw new Error("Pretty sure it's impossible for this to be reached"); | |
} | |
function convertAvscRecordToTsInterface(avscRecord: AvscRecord) { | |
const interfaceName = ts.createIdentifier(avscRecord.name); | |
const properties = avscRecord.fields.map( | |
convertAvscFieldToTsPropertySignature | |
); | |
return ts.createInterfaceDeclaration( | |
undefined, | |
undefined, | |
interfaceName, | |
undefined, | |
undefined, | |
properties | |
); | |
} | |
const resultFile = ts.createSourceFile( | |
"someFileName.ts", | |
"", | |
ts.ScriptTarget.Latest, | |
false, | |
ts.ScriptKind.TS | |
); | |
const printer = ts.createPrinter({ newLine: ts.NewLineKind.LineFeed }); | |
const test: AvscRecord = { | |
name: "Foo", | |
namespace: "foo.foo", | |
fields: [ | |
{ name: "bar", type: ["string", "null"] }, | |
{ name: "baz", type: "string" }, | |
{ name: "bop", type: "int" }, | |
], | |
}; | |
const result = printer.printNode( | |
ts.EmitHint.Unspecified, | |
convertAvscRecordToTsInterface(test), | |
resultFile | |
); | |
console.log(result); | |
//Output: | |
interface Foo { | |
bar: string | null; | |
baz: string; | |
bop: number; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment