Skip to content

Commit 93d87b4

Browse files
authored
Update destructure logic: don't destructure classes (#77)
1 parent 21fe5df commit 93d87b4

File tree

2 files changed

+52
-8
lines changed

2 files changed

+52
-8
lines changed

type-generation/src/astToIR.ts

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -204,8 +204,6 @@ function literalTypeToIR(typeNode: LiteralTypeNode): TypeIR {
204204
* If the parameter of sig is an Interface, from Python we allow the interface
205205
* entries to be passed as keyword arguments. Return the InterfaceDeclaration if
206206
* the last parameter is an interface, else return undefined.
207-
*
208-
* TODO: make this work for type literals too?
209207
*/
210208
function getInterfaceDeclToDestructure(
211209
sig: Signature,
@@ -221,17 +219,23 @@ function getInterfaceDeclToDestructure(
221219
if (typeLiteral) {
222220
return typeLiteral;
223221
}
224-
222+
// If it's a type parameter, don't try to destructure.
223+
if (typeNode.getType().isTypeParameter()) {
224+
return undefined;
225+
}
225226
// Handle named interface types (TypeReference)
226-
const defs = typeNode
227+
const ident = typeNode
227228
.asKind(SyntaxKind.TypeReference)
228229
?.getTypeName()
229-
?.asKind(SyntaxKind.Identifier)
230-
?.getDefinitionNodes();
231-
if (!defs?.length) {
230+
.asKind(SyntaxKind.Identifier);
231+
if (!ident) {
232232
return undefined;
233233
}
234-
return defs[0].asKind(SyntaxKind.InterfaceDeclaration);
234+
const classified = classifyIdentifier(ident);
235+
if (classified.kind === "interfaces") {
236+
return classified.ifaces[0];
237+
}
238+
return undefined;
235239
}
236240

237241
function getFilteredTypeParams<T extends TypeParameteredNode>(

type-generation/tests/a.test.ts

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1379,6 +1379,46 @@ describe("emit", () => {
13791379
`).trim(),
13801380
);
13811381
});
1382+
it("don't destructure class", () => {
1383+
// At some point we had an extra popNameContext() in sigToIRDestructure()
1384+
// and this test failed.
1385+
const res = emitFile(`
1386+
interface C {
1387+
a: string;
1388+
}
1389+
declare var C: {
1390+
prototype: C;
1391+
new(): C;
1392+
};
1393+
declare function f(c: C): void;
1394+
`);
1395+
assert.strictEqual(
1396+
removeTypeIgnores(res.slice(1).join("\n\n")),
1397+
dedent(`
1398+
def f(c: C, /) -> None: ...
1399+
1400+
class C(C_iface, _JsObject):
1401+
@classmethod
1402+
def new(self, /) -> C: ...
1403+
1404+
class C_iface(Protocol):
1405+
a: str = ...
1406+
`).trim(),
1407+
);
1408+
});
1409+
it("don't destructure type param", () => {
1410+
// At some point we had an extra popNameContext() in sigToIRDestructure()
1411+
// and this test failed.
1412+
const res = emitFile(`
1413+
declare function f<T>(a : T): void
1414+
`);
1415+
assert.strictEqual(
1416+
removeTypeIgnores(res.slice(1).join("\n\n")),
1417+
dedent(`
1418+
def f[T](a: T, /) -> None: ...
1419+
`).trim(),
1420+
);
1421+
});
13821422
});
13831423
describe("Type literals", () => {
13841424
it("simple", () => {

0 commit comments

Comments
 (0)