From 42878a086477f1301e6c25a2c7f79ea1ddfd31b6 Mon Sep 17 00:00:00 2001 From: Jordan Eldredge Date: Wed, 21 Jan 2026 16:06:14 -0800 Subject: [PATCH] Readonly arrays --- src/Extractor.ts | 4 ++ .../arguments/ReadonlyArrayOfString.ts | 7 +++ .../ReadonlyArrayOfString.ts.expected.md | 53 +++++++++++++++++++ website/docs/07-changelog/index.md | 1 + 4 files changed, 65 insertions(+) create mode 100644 src/tests/fixtures/arguments/ReadonlyArrayOfString.ts create mode 100644 src/tests/fixtures/arguments/ReadonlyArrayOfString.ts.expected.md diff --git a/src/Extractor.ts b/src/Extractor.ts index fc561ba3..27182129 100644 --- a/src/Extractor.ts +++ b/src/Extractor.ts @@ -2624,6 +2624,10 @@ class Extractor { return this.report(node, E.ambiguousNumberType()); } else if (ts.isTypeLiteralNode(node)) { return this.report(node, E.unsupportedTypeLiteral()); + } else if (ts.isTypeOperatorNode(node)) { + if (node.operator === ts.SyntaxKind.ReadonlyKeyword) { + return this.collectType(node.type, ctx); + } } // TODO: Better error message. This is okay if it's a type reference, but everything else is not. this.reportUnhandled(node, "type", E.unknownGraphQLType()); diff --git a/src/tests/fixtures/arguments/ReadonlyArrayOfString.ts b/src/tests/fixtures/arguments/ReadonlyArrayOfString.ts new file mode 100644 index 00000000..18bea754 --- /dev/null +++ b/src/tests/fixtures/arguments/ReadonlyArrayOfString.ts @@ -0,0 +1,7 @@ +/** @gqlType */ +export default class SomeType { + /** @gqlField */ + hello(greetings: readonly string[]): string { + return `${greetings.join(", ")} world!`; + } +} diff --git a/src/tests/fixtures/arguments/ReadonlyArrayOfString.ts.expected.md b/src/tests/fixtures/arguments/ReadonlyArrayOfString.ts.expected.md new file mode 100644 index 00000000..340029c6 --- /dev/null +++ b/src/tests/fixtures/arguments/ReadonlyArrayOfString.ts.expected.md @@ -0,0 +1,53 @@ +# arguments/ReadonlyArrayOfString.ts + +## Input + +```ts title="arguments/ReadonlyArrayOfString.ts" +/** @gqlType */ +export default class SomeType { + /** @gqlField */ + hello(greetings: readonly string[]): string { + return `${greetings.join(", ")} world!`; + } +} +``` + +## Output + +### SDL + +```graphql +type SomeType { + hello(greetings: [String!]!): String +} +``` + +### TypeScript + +```ts +import { GraphQLSchema, GraphQLObjectType, GraphQLString, GraphQLNonNull, GraphQLList } from "graphql"; +export function getSchema(): GraphQLSchema { + const SomeTypeType: GraphQLObjectType = new GraphQLObjectType({ + name: "SomeType", + fields() { + return { + hello: { + name: "hello", + type: GraphQLString, + args: { + greetings: { + type: new GraphQLNonNull(new GraphQLList(new GraphQLNonNull(GraphQLString))) + } + }, + resolve(source, args) { + return source.hello(args.greetings); + } + } + }; + } + }); + return new GraphQLSchema({ + types: [SomeTypeType] + }); +} +``` \ No newline at end of file diff --git a/website/docs/07-changelog/index.md b/website/docs/07-changelog/index.md index 8e06cdbb..80427bab 100644 --- a/website/docs/07-changelog/index.md +++ b/website/docs/07-changelog/index.md @@ -4,6 +4,7 @@ - **Features** - Added support for async derived context functions. Derived context functions can now return `Promise` and Grats will automatically generate the necessary `await` expressions in resolver code. + - Added support for `readonly T[]` as parsable GraphQL types. Changes in this section are not yet released. If you need access to these changes before we cut a release, check out our `@main` NPM releases. Each commit on the main branch is [published to NPM](https://www.npmjs.com/package/grats?activeTab=versions) under the `main` tag.