Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 13 additions & 5 deletions type-generation/src/astToIR.ts
Original file line number Diff line number Diff line change
Expand Up @@ -406,16 +406,24 @@ class SyntheticTypeConverter {
.getTypeNodes()
.map((ty, idx) => {
this.nameContext.push(`Intersection${idx}`);
// In TS it's just fine to use the LHS of a type alias in an
// intersection. However, in Python we can't inherit from a type
// alias. So if the reference target is a type alias, we have to
// unwind it until we hit something we can inherit.
while (Node.isTypeReference(ty)) {
const classified = classifyIdentifier(
ty.getTypeName() as Identifier,
);
if (classified.kind !== "typeAlias") {
break;
}
ty = classified.decl.getTypeNode()!;
}
const res = this.typeToIR(ty, modifiers);
this.nameContext.pop();
return res;
})
.filter((x): x is ReferenceTypeIR => !!x && x.kind === "reference");
for (const x of types) {
if (!x.name.endsWith("_iface")) {
x.name += "_iface";
}
}
const name = this.nameContext.join("__") + "_iface";
this.converter.extraTopLevels.push(
this.converter.interfaceToIR(name, types, [], [], [], []),
Expand Down
37 changes: 32 additions & 5 deletions type-generation/tests/a.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1456,19 +1456,46 @@ describe("emit", () => {
dedent(`
type D = D_iface

type F = F_iface

def f() -> D: ...

class D__Intersection0_iface(Protocol):
a: str = ...

class D__Intersection1_iface(Protocol):
@property
def id(self, /) -> int | float: ...

class D_iface(F_iface, D__Intersection1_iface, Protocol):
class D_iface(D__Intersection1_iface, D__Intersection0_iface, Protocol):
pass
`).trim(),
);
});
it("intersection3", () => {
const res = emitFile(`
interface I<T> {
x: T;
}
type F = I<string>;
type D = F & {
id: number;
};
declare function f(): D;
`);
assert.strictEqual(
removeTypeIgnores(res.slice(1).join("\n\n")),
dedent(`
type D = D_iface

class F_iface(Protocol):
a: str = ...
def f() -> D: ...

class I_iface[T](Protocol):
x: T = ...

class D__Intersection1_iface(Protocol):
id: int | float = ...

class D_iface(D__Intersection1_iface, I_iface[str], Protocol):
pass
`).trim(),
);
});
Expand Down