Skip to content

Commit

Permalink
feat: support referencing generic types from anywhere
Browse files Browse the repository at this point in the history
  • Loading branch information
elyukai committed Mar 10, 2022
1 parent 90987bd commit 09ba488
Showing 1 changed file with 28 additions and 29 deletions.
57 changes: 28 additions & 29 deletions src/ast.ts
Original file line number Diff line number Diff line change
Expand Up @@ -538,37 +538,32 @@ const nodeToAst = (node: ts.Node, checker: ts.TypeChecker, typeArguments: { [nam
const symbol = checker.getSymbolAtLocation(node.typeName)

if (node.typeArguments && node.typeArguments.length > 0) {
if (ts.isTypeAliasDeclaration(node.parent)) {
const nodeWithTypeParameters = symbol?.declarations?.[0]!
const nodeWithTypeParameters = symbol?.declarations?.[0]!

const typeParameters = (() => {
if (ts.isTypeAliasDeclaration(nodeWithTypeParameters)) {
return nodeWithTypeParameters.typeParameters ?? []
}
else {
throw new Error(`resolving type parameters from referenced node of type "${ts.SyntaxKind[nodeWithTypeParameters.kind]}" is currently not supported`)
}
})()
const typeParameters = (() => {
if (ts.isTypeAliasDeclaration(nodeWithTypeParameters)) {
return nodeWithTypeParameters.typeParameters ?? []
}
else {
throw new Error(`resolving type parameters from referenced node of type "${ts.SyntaxKind[nodeWithTypeParameters.kind]}" is currently not supported`)
}
})()

const newTypeArguments = node.typeArguments.map(
typeNode => nodeToAst(typeNode, checker, typeArguments)
)
const newTypeArguments = node.typeArguments.map(
typeNode => nodeToAst(typeNode, checker, typeArguments)
)

if (typeParameters.length !== newTypeArguments.length) {
throw new Error(`resolving type parameters failed due to a different number of arguments provided`)
}
if (typeParameters.length !== newTypeArguments.length) {
throw new Error(`resolving type parameters failed due to a different number of arguments provided`)
}

const newTypeArgumentsMap = Object.fromEntries(
typeParameters.map(
(key, index) => [key.name.text, newTypeArguments[index]!]
)
const newTypeArgumentsMap = Object.fromEntries(
typeParameters.map(
(key, index) => [key.name.text, newTypeArguments[index]!]
)
)

return nodeToAst(nodeWithTypeParameters, checker, newTypeArgumentsMap)
}
else {
throw new Error(`resolving type parameters from parent node of type "${ts.SyntaxKind[node.parent.kind]}" is currently not supported`)
}
return nodeToAst(nodeWithTypeParameters, checker, newTypeArgumentsMap)
}
else {
const name = ts.isIdentifier(node.typeName)
Expand All @@ -579,10 +574,6 @@ const nodeToAst = (node: ts.Node, checker: ts.TypeChecker, typeArguments: { [nam

const parentGroup = symbol ? traverseAbsoluteParentModules(symbol, checker) : undefined

if (parentGroup === undefined && name in typeArguments) {
return typeArguments[name]!
}

const outerMostReference =
parentGroup
? outerMostGroupName(parentGroup)
Expand All @@ -593,6 +584,14 @@ const nodeToAst = (node: ts.Node, checker: ts.TypeChecker, typeArguments: { [nam
? outerMostQualifiedName(node.typeName)
: undefined

if (
parentGroup === undefined
&& alternativeOuterMostReference === undefined
&& name in typeArguments
) {
return typeArguments[name]!
}

const importNodes = node.getSourceFile().statements.filter(ts.isImportDeclaration)

const matchingImportNode = importNodes.find(importNode => {
Expand Down

0 comments on commit 09ba488

Please sign in to comment.