feat: Extend type injection to all exported values
This commit is contained in:
parent
d5b4ccfc2a
commit
66bf2e281a
@ -17,7 +17,8 @@ export const Complex_type = {
|
||||
(z: Complex<unknown>) => joinTypes(dep.typeOf(z.re), dep.typeOf(z.im)),
|
||||
from: {
|
||||
Complex: <U,T>(dep: {convert: CommonSignature<U,T>['convert']}) =>
|
||||
(z: Complex<U>) => ({re: dep.convert(z.re), im: dep.convert(z.im)}),
|
||||
(z: Complex<U>): Complex<T> =>
|
||||
({re: dep.convert(z.re), im: dep.convert(z.im)}),
|
||||
T: <T>(dep: {zero: CommonSignature<T>['zero']}) =>
|
||||
(t: T) => ({re: t, im: dep.zero(t)})
|
||||
}
|
||||
|
@ -2,4 +2,4 @@ import {inspect} from 'node:util'
|
||||
|
||||
import * as specifications from './all'
|
||||
|
||||
console.log(inspect(specifications, {depth: 10, colors: true}))
|
||||
console.log(inspect(specifications, {depth: 18, colors: true}))
|
||||
|
@ -49,7 +49,7 @@ function reflectType5(srcFile, options = { debug: false }) {
|
||||
for (const id in parsedDefs) {
|
||||
if (id.includes('interface')) continue
|
||||
srcReflected +=
|
||||
`\n${id}.reflectedType6 = ${JSON.stringify(parsedDefs[id])}\n`
|
||||
`\n${id}._reflectedType6 = ${JSON.stringify(parsedDefs[id])}\n`
|
||||
}
|
||||
writeFileSync(srcFile, srcReflected)
|
||||
|
||||
|
@ -1,11 +1,21 @@
|
||||
import * as ts from 'typescript'
|
||||
|
||||
const PROPERTY_TYPES = {
|
||||
any: ts.SyntaxKind.AnyKeyword,
|
||||
boolean: ts.SyntaxKind.BooleanKeyword,
|
||||
number: ts.SyntaxKind.NumberKeyword,
|
||||
string: ts.SyntaxKind.StringKeyword,
|
||||
}
|
||||
const intrinsicTypeKeywords = new Set([
|
||||
ts.SyntaxKind.AnyKeyword,
|
||||
ts.SyntaxKind.BooleanKeyword,
|
||||
ts.SyntaxKind.NeverKeyword,
|
||||
ts.SyntaxKind.NumberKeyword,
|
||||
ts.SyntaxKind.StringKeyword,
|
||||
ts.SyntaxKind.UndefinedKeyword,
|
||||
ts.SyntaxKind.UnknownKeyword,
|
||||
ts.SyntaxKind.VoidKeyword
|
||||
])
|
||||
|
||||
const typeOperatorKeywords = new Map([
|
||||
[ts.SyntaxKind.KeyofKeyword, '_keyof'],
|
||||
[ts.SyntaxKind.ReadonlyKeyword, '_readonly'],
|
||||
[ts.SyntaxKind.UniqueKeyword, '_unique'],
|
||||
])
|
||||
|
||||
class TSNode {
|
||||
constructor(name, type) {
|
||||
@ -41,32 +51,90 @@ class TSNode {
|
||||
}
|
||||
}
|
||||
|
||||
function parameterTypeStructure(paramNode, checker) {
|
||||
let typeStruc = typeStructure(paramNode.type, checker)
|
||||
if (paramNode.questionToken) typeStruc = {_optional: typeStruc}
|
||||
return typeStruc
|
||||
}
|
||||
|
||||
function typeStructure(typeNode, checker) {
|
||||
switch (typeNode.kind) {
|
||||
case ts.SyntaxKind.UnionType:
|
||||
return {
|
||||
_union: typeNode.types.map(t => typeStructure(t, checker))
|
||||
}
|
||||
case ts.SyntaxKind.IntersectionType:
|
||||
return {
|
||||
_intersection: typeNode.types.map(t => typeStructure(t, checker))
|
||||
}
|
||||
case ts.SyntaxKind.ImportType:
|
||||
return {
|
||||
case ts.SyntaxKind.ImportType: {
|
||||
const typeStruc = {
|
||||
_importedFrom: typeNode.argument.literal.text,
|
||||
_name: typeNode.qualifier.text
|
||||
}
|
||||
case ts.SyntaxKind.TypeLiteral:
|
||||
if (typeNode.typeArguments) {
|
||||
typeStruc._typeArguments = typeNode.typeArguments.map(
|
||||
p => typeStructure(p, checker))
|
||||
}
|
||||
return typeStruc
|
||||
}
|
||||
case ts.SyntaxKind.ArrayType:
|
||||
return {_array: typeStructure(typeNode.elementType, checker)}
|
||||
case ts.SyntaxKind.TypeLiteral: // Seems to be plain object types
|
||||
return Object.fromEntries(typeNode.members.map(
|
||||
mem => [mem.name.text, typeStructure(mem.type, checker)]))
|
||||
case ts.SyntaxKind.FunctionType:
|
||||
return {
|
||||
case ts.SyntaxKind.FunctionType: {
|
||||
const typeStruc = {
|
||||
_parameters: typeNode.parameters.map(
|
||||
p => typeStructure(p.type, checker)),
|
||||
p => parameterTypeStructure(p, checker)),
|
||||
_returns: typeStructure(typeNode.type, checker)
|
||||
}
|
||||
if (typeNode.typeParameters) {
|
||||
typeStruc._typeParameters = typeNode.typeParameters.map(
|
||||
p => p.name.text)
|
||||
}
|
||||
return typeStruc
|
||||
}
|
||||
case ts.SyntaxKind.IndexedAccessType:
|
||||
return {
|
||||
_ofType: typeStructure(typeNode.objectType, checker),
|
||||
_index: typeStructure(typeNode.indexType, checker)
|
||||
}
|
||||
case ts.SyntaxKind.TypeOperator:
|
||||
console.log('structuring operator', typeNode)
|
||||
const key = typeOperatorKeywords.get(
|
||||
typeNode.operator,
|
||||
'_unidentified_operator'
|
||||
)
|
||||
return {
|
||||
[key]:
|
||||
typeStructure(typeNode.type, checker)
|
||||
}
|
||||
case ts.SyntaxKind.ConditionalType:
|
||||
return {
|
||||
_subtype: typeStructure(typeNode.checkType, checker),
|
||||
_basetype: typeStructure(typeNode.extendsType, checker),
|
||||
_truetype: typeStructure(typeNode.trueType, checker),
|
||||
_falsetype: typeStructure(typeNode.falseType, checker),
|
||||
}
|
||||
case ts.SyntaxKind.TypeReference: {
|
||||
const typeStruc = {_typeParameter: typeNode.typeName.text}
|
||||
if (typeNode.typeArguments) {
|
||||
typeStruc._typeArguments = typeNode.typeArguments.map(
|
||||
arg => typeStructure(arg, checker))
|
||||
}
|
||||
return typeStruc
|
||||
}
|
||||
case ts.SyntaxKind.TypePredicate:
|
||||
return {_is: typeStructure(typeNode.type, checker)}
|
||||
case ts.SyntaxKind.LiteralType:
|
||||
return checker.typeToString(checker.getTypeFromTypeNode(typeNode))
|
||||
default:
|
||||
console.log('I See', ts.SyntaxKind[typeNode.kind])
|
||||
}
|
||||
if (intrinsicTypeKeywords.has(typeNode.kind)) {
|
||||
return checker.getTypeFromTypeNode(typeNode).intrinsicName
|
||||
}
|
||||
}
|
||||
throw new Error(`Unhandled type node ${ts.SyntaxKind[typeNode.kind]}`)
|
||||
}
|
||||
|
||||
const visit = (parent, checker) => node => {
|
||||
@ -80,15 +148,26 @@ const visit = (parent, checker) => node => {
|
||||
node.declarationList.declarations.forEach(visit(parent, checker))
|
||||
console.log('Done with variable')
|
||||
break
|
||||
case ts.SyntaxKind.VariableDeclaration:
|
||||
console.log('Processing var dec', node.name.text, 'in', parent)
|
||||
case ts.SyntaxKind.VariableDeclaration: {
|
||||
console.log('Processing var dec', node.name.text)
|
||||
const typeStruc = typeStructure(node.type, checker)
|
||||
console.log('Type is', typeStructure(node.type, checker))
|
||||
if ('_intersection' in typeStruc) {
|
||||
console.log('First type is', typeStruc._intersection[0])
|
||||
parent.addChild(node.name.text, typeStruc)
|
||||
break
|
||||
}
|
||||
case ts.SyntaxKind.FunctionDeclaration: {
|
||||
console.log('Processing func dec', node.name.text)
|
||||
const typeStruc = {
|
||||
_parameters: node.parameters.map(
|
||||
p => parameterTypeStructure(p, checker)),
|
||||
_returns: typeStructure(node.type, checker)
|
||||
}
|
||||
if (node.typeParameters) {
|
||||
typeStruc._typeParameters = node.typeParameters.map(
|
||||
p => p.name.text)
|
||||
}
|
||||
parent.addChild(node.name.text, typeStruc)
|
||||
break
|
||||
}
|
||||
case ts.SyntaxKind.ModuleDeclaration:
|
||||
let moduleName = node.name.text
|
||||
console.log('Declaring', moduleName)
|
||||
@ -131,13 +210,15 @@ const visit = (parent, checker) => node => {
|
||||
'>'.repeat(arrayDeep)
|
||||
)
|
||||
} else {
|
||||
for (let type in PROPERTY_TYPES) {
|
||||
if (propertyType.kind === PROPERTY_TYPES[type]) {
|
||||
parent.addChild(realPropertyName, type)
|
||||
if (intrinsicTypeKeywords.has(propertyType.kind)) {
|
||||
parent.addChild(
|
||||
realPropertyName,
|
||||
checker.getTypeFromTypeNode(propertyType).intrinsicName)
|
||||
}
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
case ts.SyntaxKind.EndOfFileToken:
|
||||
console.log('File ended.')
|
||||
break
|
||||
default:
|
||||
console.warn(
|
||||
|
Loading…
Reference in New Issue
Block a user