Skip to content

Commit

Permalink
fix: Reintroduce support for index signatures
Browse files Browse the repository at this point in the history
  • Loading branch information
Gerrit0 committed Dec 27, 2020
1 parent 5e5e875 commit 20a7d5f
Show file tree
Hide file tree
Showing 5 changed files with 425 additions and 198 deletions.
55 changes: 55 additions & 0 deletions src/lib/converter/factories/index-signature.ts
@@ -0,0 +1,55 @@
import * as assert from "assert";
import * as ts from "typescript";
import {
DeclarationReflection,
ParameterReflection,
ReflectionKind,
SignatureReflection,
} from "../../models";
import { Context } from "../context";
import { ConverterEvents } from "../converter-events";

export function convertIndexSignature(context: Context, symbol: ts.Symbol) {
assert(context.scope instanceof DeclarationReflection);

const indexSymbol = symbol.members?.get("__index" as ts.__String);
if (indexSymbol) {
// Right now TypeDoc models don't have a way to distinguish between string
// and number index signatures... { [x: string]: 1 | 2; [x: number]: 2 }
// will be misrepresented.
const indexDeclaration = indexSymbol.getDeclarations()?.[0];
assert(
indexDeclaration && ts.isIndexSignatureDeclaration(indexDeclaration)
);
const param = indexDeclaration.parameters[0];
assert(param && ts.isParameter(param));
const index = new SignatureReflection(
"__index",
ReflectionKind.IndexSignature,
context.scope
);
index.parameters = [
new ParameterReflection(
param.name.getText(),
ReflectionKind.Parameter,
index
),
];
index.parameters[0].type = context.converter.convertType(
context.withScope(index.parameters[0]),
param.type
);
index.type = context.converter.convertType(
context.withScope(index),
indexDeclaration.type
);
context.registerReflection(index, indexSymbol);
context.trigger(
ConverterEvents.CREATE_SIGNATURE,
index,
indexDeclaration
);

context.scope.indexSignature = index;
}
}
6 changes: 4 additions & 2 deletions src/lib/converter/symbols.ts
Expand Up @@ -13,10 +13,9 @@ import { getEnumFlags, hasFlag, removeFlag } from "../utils/enum";
import { Context } from "./context";
import { convertDefaultValue } from "./convert-expression";
import { ConverterEvents } from "./converter-events";
import { convertIndexSignature } from "./factories/index-signature";
import { createSignature } from "./factories/signature";

// TODO: Index signatures

function getSymbolExportsWithFlag(symbol: ts.Symbol, flag: ts.SymbolFlags) {
const childSymbols: ts.Symbol[] = [];

Expand Down Expand Up @@ -438,6 +437,9 @@ function convertClassOrInterface(
// We also might have constructor signatures
// This is potentially a problem with classes having
convertConstructSignatures(reflectionContext, symbol);

// And finally, index signatures
convertIndexSignature(reflectionContext, symbol);
}

function convertProperty(
Expand Down
13 changes: 5 additions & 8 deletions src/lib/converter/types.ts
Expand Up @@ -27,6 +27,7 @@ import { TemplateLiteralType } from "../models/types/template-literal";
import { zip } from "../utils/array";
import { Context } from "./context";
import { ConverterEvents } from "./converter-events";
import { convertIndexSignature } from "./factories/index-signature";
import {
convertParameterNodes,
convertTypeParameterNodes,
Expand Down Expand Up @@ -417,6 +418,8 @@ const typeLiteralConverter: TypeConverter<ts.TypeLiteralNode> = {
);
}

convertIndexSignature(context.withScope(reflection), symbol);

return new ReflectionType(reflection);
},
convertType(context, type) {
Expand Down Expand Up @@ -446,6 +449,8 @@ const typeLiteralConverter: TypeConverter<ts.TypeLiteralNode> = {
);
}

convertIndexSignature(context.withScope(reflection), type.symbol);

return new ReflectionType(reflection);
},
};
Expand Down Expand Up @@ -487,14 +492,6 @@ const referenceConverter: TypeConverter<
kind: [ts.SyntaxKind.TypeReference],
convert(context, node) {
const symbol = context.expectSymbolAtLocation(node.typeName);
// We might need to resolve this type (e.g a parent class has a property with a generic type)
// but we are in a child type, so the generic type should be resolved to a concrete one.
if (symbol.flags & ts.SymbolFlags.TypeParameter) {
// if (!isErrorType(resolvedType) && !resolvedType.isTypeParameter()) {
// return convertType(context, resolvedType);
// }
// TODO: Fix type parameters
}

const name = node.typeName.getText();

Expand Down
15 changes: 15 additions & 0 deletions src/test/converter/interface/index-signature.ts
@@ -0,0 +1,15 @@
export interface StrIndex {
[x: string]: 1;
}

export interface NumIndex {
[x: number]: 1;
}

// This is broken... but here's a test for the broken behavior so we know when it is fixed.
export interface BothIndex {
[x: number]: 1;
[x: string]: 1 | 2;
}

export type TypeIndex = { [x: string]: 1 };

0 comments on commit 20a7d5f

Please sign in to comment.