Skip to content

Commit 65745b9

Browse files
committed
Handle edge cases with namespaced types
1 parent b47678f commit 65745b9

File tree

4 files changed

+160
-8
lines changed

4 files changed

+160
-8
lines changed

src/parsers/typeResolver.ts

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -45,18 +45,27 @@ export function resolveType(
4545
let typeSymbol: ts.Symbol | undefined;
4646
if (typeNode && ts.isTypeReferenceNode(typeNode)) {
4747
const typeNodeName = (typeNode as ts.TypeReferenceNode).typeName;
48-
if (ts.isIdentifier(typeNodeName) && typeNodeName.text !== type.aliasSymbol?.name) {
48+
if (ts.isIdentifier(typeNodeName)) {
4949
const typeSymbolCandidate = checker.getSymbolAtLocation(typeNodeName);
50-
if (typeSymbolCandidate && !(typeSymbolCandidate.flags & ts.SymbolFlags.TypeParameter)) {
50+
51+
if (
52+
typeSymbolCandidate &&
53+
(typeNodeName.text !== type.aliasSymbol?.name ||
54+
getTypeSymbolNamespaces(typeSymbolCandidate).join('.') !==
55+
getTypeNamespaces(type).join('.')) &&
56+
!(typeSymbolCandidate.flags & ts.SymbolFlags.TypeParameter)
57+
) {
5158
typeSymbol = typeSymbolCandidate;
5259
}
53-
} else if (
54-
ts.isQualifiedName(typeNodeName) &&
55-
typeNodeName.right.text !== type.aliasSymbol?.name /*&&
56-
typeNodeName.left.getFullText() !== getTypeNamespaces(type).join('.')*/
57-
) {
60+
} else if (ts.isQualifiedName(typeNodeName)) {
5861
const typeSymbolCandidate = checker.getSymbolAtLocation(typeNodeName.right);
59-
if (typeSymbolCandidate && !(typeSymbolCandidate.flags & ts.SymbolFlags.TypeParameter)) {
62+
if (
63+
typeSymbolCandidate &&
64+
(typeNodeName.right.text !== type.aliasSymbol?.name ||
65+
getTypeSymbolNamespaces(typeSymbolCandidate).join('.') !==
66+
getTypeNamespaces(type).join('.')) &&
67+
!(typeSymbolCandidate.flags & ts.SymbolFlags.TypeParameter)
68+
) {
6069
typeSymbol = typeSymbolCandidate;
6170
}
6271
}
@@ -123,6 +132,9 @@ export function resolveType(
123132
// @ts-expect-error - Internal API
124133
if (type.origin?.isUnion()) {
125134
// @ts-expect-error - Internal API
135+
136+
// If a union type contains another union, `type.types` will contain the flattened types.
137+
// To resolve the original union type, we need to use the internal `type.origin.types`.
126138
memberTypes = type.origin.types;
127139
}
128140

test/namespaces-nested/input.tsx

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import type { Foo as AliasedFoo } from './types';
2+
3+
export namespace Root {
4+
export type Foo = AliasedFoo;
5+
6+
export namespace Nested {
7+
export type Foo = AliasedFoo;
8+
}
9+
10+
export interface Props {
11+
foo: Foo;
12+
nestedFoo: Nested.Foo;
13+
}
14+
}
15+
16+
export function Component(props: Root.Props) {
17+
return <div />;
18+
}

test/namespaces-nested/output.json

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
{
2+
"name": "test/namespaces-nested/input",
3+
"exports": [
4+
{
5+
"name": "Component",
6+
"type": {
7+
"kind": "component",
8+
"name": "Component",
9+
"parentNamespaces": [],
10+
"props": [
11+
{
12+
"name": "foo",
13+
"type": {
14+
"kind": "union",
15+
"types": [
16+
{
17+
"kind": "literal",
18+
"parentNamespaces": [],
19+
"value": "\"a\""
20+
},
21+
{
22+
"kind": "literal",
23+
"parentNamespaces": [],
24+
"value": "\"b\""
25+
}
26+
],
27+
"parentNamespaces": [
28+
"Root"
29+
],
30+
"name": "Foo"
31+
},
32+
"optional": false
33+
},
34+
{
35+
"name": "nestedFoo",
36+
"type": {
37+
"kind": "union",
38+
"types": [
39+
{
40+
"kind": "literal",
41+
"parentNamespaces": [],
42+
"value": "\"a\""
43+
},
44+
{
45+
"kind": "literal",
46+
"parentNamespaces": [],
47+
"value": "\"b\""
48+
}
49+
],
50+
"parentNamespaces": [
51+
"Root",
52+
"Nested"
53+
],
54+
"name": "Foo"
55+
},
56+
"optional": false
57+
}
58+
]
59+
}
60+
},
61+
{
62+
"name": "Props",
63+
"type": {
64+
"kind": "object",
65+
"name": "Props",
66+
"parentNamespaces": [
67+
"Root"
68+
],
69+
"properties": [
70+
{
71+
"name": "foo",
72+
"type": {
73+
"kind": "union",
74+
"types": [
75+
{
76+
"kind": "literal",
77+
"parentNamespaces": [],
78+
"value": "\"a\""
79+
},
80+
{
81+
"kind": "literal",
82+
"parentNamespaces": [],
83+
"value": "\"b\""
84+
}
85+
],
86+
"parentNamespaces": [
87+
"Root"
88+
],
89+
"name": "Foo"
90+
},
91+
"optional": false
92+
},
93+
{
94+
"name": "nestedFoo",
95+
"type": {
96+
"kind": "union",
97+
"types": [
98+
{
99+
"kind": "literal",
100+
"parentNamespaces": [],
101+
"value": "\"a\""
102+
},
103+
{
104+
"kind": "literal",
105+
"parentNamespaces": [],
106+
"value": "\"b\""
107+
}
108+
],
109+
"parentNamespaces": [
110+
"Root",
111+
"Nested"
112+
],
113+
"name": "Foo"
114+
},
115+
"optional": false
116+
}
117+
]
118+
}
119+
}
120+
]
121+
}

test/namespaces-nested/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export type Foo = 'a' | 'b';

0 commit comments

Comments
 (0)