Repository: alloy-framework/alloy
Pull request #13 (2024-08-27 19:29:49)

Interface member optional and readonly
Add props to set an interface member as optional and readonly

pkg-pr-new[bot]: 
_commit: <a href="https://github.com/alloy-framework/alloy/runs/29329311957"><code>12574f2</code></a>_


<details><summary><b>@alloy-js/babel-plugin-alloy</b></summary><p>

```
pnpm add https://pkg.pr.new/alloy-framework/alloy/@alloy-js/babel-plugin-alloy@13
```

</p></details>
      
    

<details><summary><b>@alloy-js/babel-plugin-jsx-dom-expressions</b></summary><p>

```
pnpm add https://pkg.pr.new/alloy-framework/alloy/@alloy-js/babel-plugin-jsx-dom-expressions@13
```

</p></details>
      
    

<details><summary><b>babel-preset-alloy</b></summary><p>

```
pnpm add https://pkg.pr.new/alloy-framework/alloy/babel-preset-alloy@13
```

</p></details>
      
    

<details><summary><b>@alloy-js/core</b></summary><p>

```
pnpm add https://pkg.pr.new/alloy-framework/alloy/@alloy-js/core@13
```

</p></details>
      
    

<details><summary><b>@alloy-js/java</b></summary><p>

```
pnpm add https://pkg.pr.new/alloy-framework/alloy/@alloy-js/java@13
```

</p></details>
      
    

<details><summary><b>@alloy-js/prettier-plugin-alloy</b></summary><p>

```
pnpm add https://pkg.pr.new/alloy-framework/alloy/@alloy-js/prettier-plugin-alloy@13
```

</p></details>
      
    

<details><summary><b>@alloy-js/typescript</b></summary><p>

```
pnpm add https://pkg.pr.new/alloy-framework/alloy/@alloy-js/typescript@13
```

</p></details>
      
    

[Open in Stackblitz](https://pkg.pr.new/template/a8c12ddd-349c-4e54-9fd6-bd7ef4a5a2f3)


Patch:
diff --git a/packages/typescript/src/components/Interface.tsx b/packages/typescript/src/components/Interface.tsx
index f1e1d62..999d34c 100644
--- a/packages/typescript/src/components/Interface.tsx
+++ b/packages/typescript/src/components/Interface.tsx
@@ -34,14 +34,18 @@ export interface InterfaceMemberProps {
   indexer?: Children;
   type?: Children;
   children?: Children;
+  optional?: boolean;
+  readonly?: boolean;
 }
 
 export function InterfaceMember(props: InterfaceMemberProps) {
   const namer = useTSNamePolicy();
   const type = props.type ?? props.children;
+  const optionality = props.optional ? "?" : "";
+  const readonly = props.readonly ? "readonly " : "";
   if (props.indexer) {
     return <>[{props.indexer}]: {type}</>;
   } else {
-    return <>{namer.getName(props.name!, "interface-member")}: {type}</>;
+    return <>{readonly}{namer.getName(props.name!, "interface-member")}{optionality}: {type}</>;
   }
 }


Test patch:
diff --git a/packages/typescript/test/interface.test.tsx b/packages/typescript/test/interface.test.tsx
index 5de1c86..ef61877 100644
--- a/packages/typescript/test/interface.test.tsx
+++ b/packages/typescript/test/interface.test.tsx
@@ -57,6 +57,42 @@ it("can create members", () => {
   `);
 });
 
+it("can create optional members", () => {
+  const res = toSourceText(
+    <ts.InterfaceDeclaration name="Foo">
+      <ts.InterfaceMember name="member" type="string" />;
+      <ts.InterfaceMember optional name="circular" type={<Reference refkey={refkey("Foo")} />} />;
+      <ts.InterfaceMember indexer="str: string" type="number" />;
+    </ts.InterfaceDeclaration>,
+  );
+
+  expect(res).toEqual(d`
+    interface Foo {
+      member: string;
+      circular?: Foo;
+      [str: string]: number;
+    }
+  `);
+});
+
+it("can create readonly members", () => {
+  const res = toSourceText(
+    <ts.InterfaceDeclaration name="Foo">
+      <ts.InterfaceMember readonly name="member" type="string" />;
+      <ts.InterfaceMember name="circular" type={<Reference refkey={refkey("Foo")} />} />;
+      <ts.InterfaceMember indexer="str: string" type="number" />;
+    </ts.InterfaceDeclaration>,
+  );
+
+  expect(res).toEqual(d`
+    interface Foo {
+      readonly member: string;
+      circular: Foo;
+      [str: string]: number;
+    }
+  `);
+});
+
 it("has interface expressions", () => {
   const res = toSourceText(
     <ts.InterfaceExpression>