Skip to content

Commit 2ef31c7

Browse files
committed
fix(indexedAccessType): ensure compiler doesn't break for unsupported indexed access type
1 parent 9d3a424 commit 2ef31c7

File tree

4 files changed

+57
-3
lines changed

4 files changed

+57
-3
lines changed

src/transformer/descriptor/indexedAccess/indexedAccess.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,10 @@ export function GetIndexedAccessTypeDescriptor(node: ts.IndexedAccessTypeNode, s
4040
const propertySymbol: ts.Symbol | undefined = typeChecker.getPropertyOfType(typeChecker.getTypeFromTypeNode(node.objectType), propertyName);
4141

4242
if (!propertySymbol) {
43-
throw new Error(
44-
`The type checker failed to look up symbol for property: \`${propertyName}' of \`${node.getText()}'.`,
45-
);
43+
// FIXME: Currently not all IndexedAccessType transformation are supported.
44+
// See https://github.com/Typescript-TDD/ts-auto-mock/issues/201 for more details.
45+
TransformerLogger().indexedAccessTypeFailed(propertyName, node.getText());
46+
return GetNullDescriptor();
4647
}
4748

4849
return GetDescriptor(TypescriptHelper.GetDeclarationFromSymbol(propertySymbol), scope);

src/transformer/logger/transformerLogger.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ export interface TransformerLogger {
88
unexpectedCreateMock(mockFileName: string, expectedFileName: string): void;
99
typeNotSupported(type: string): void;
1010
typeOfFunctionCallNotFound(node: string): void;
11+
indexedAccessTypeFailed(propertyName: string, nodeText: string): void;
1112
}
1213

1314
export function TransformerLogger(): TransformerLogger {
@@ -31,5 +32,8 @@ export function TransformerLogger(): TransformerLogger {
3132
typeOfFunctionCallNotFound(node: string): void {
3233
logger.warning(`Cannot find type of function call: ${node} - it will convert to null`);
3334
},
35+
indexedAccessTypeFailed(propertyName: string, nodeText: string ): void {
36+
logger.warning(`IndexedAccessType transformation failed: cannot find property ${propertyName} of - ${nodeText}`);
37+
},
3438
};
3539
}

test/transformer/descriptor/indexedAccess/indexedAccess.test.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,4 +60,17 @@ describe('indexedAccess', () => {
6060
expect(mock.c.a.b).toEqual(0);
6161
expect(mock.c.b).toEqual('');
6262
});
63+
64+
it('should not break the compiler for unsupported generic', () => {
65+
interface StandardInterface {
66+
prop: string;
67+
}
68+
interface WithKeyGeneric<U extends keyof StandardInterface> {
69+
test(): StandardInterface[U];
70+
}
71+
72+
const type: WithKeyGeneric<'prop'> = createMock<WithKeyGeneric<'prop'>>();
73+
74+
expect(type.test()).toBeNull();
75+
});
6376
});

ui/src/views/types-not-supported.mdx

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,3 +95,39 @@ circle `A` over and over, and result in an infinite nested tree of declaration
9595
references. The intended behavior is to have the first back-reference stored
9696
elsewhere in the generated output and let it reference itself, making the
9797
runtime a lazy-evaluated sequence of getters.
98+
99+
## Indexed access type with generics
100+
```ts
101+
interface StandardInterface {
102+
prop: string;
103+
}
104+
105+
interface WithKeyGeneric<U extends keyof StandardInterface> {
106+
test(): StandardInterface[U];
107+
}
108+
109+
const type = createMock<WithKeyGeneric<'prop'>>();
110+
111+
expect(type.test()).toBe(''); // it will be null
112+
```
113+
114+
These are discussed here:
115+
[link](https://github.com/Typescript-TDD/ts-auto-mock/issues/201).
116+
Indexed access type it's a though feature to handle correctly.
117+
There are few difference scenarios:
118+
- From MappedTypes
119+
```ts
120+
type Test = {[key in keyof A]: A[key]};
121+
```
122+
- From Generics -> example above
123+
- From literal
124+
```ts
125+
interface StandardInterface {
126+
prop: string;
127+
}
128+
129+
type Hello = StandardInterface['prop'];
130+
```
131+
132+
133+

0 commit comments

Comments
 (0)