Skip to content
Merged
Changes from 5 commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
6715e27
Add options with param formatting from existing readme.
devalog Jul 1, 2025
cde8cfe
Add all available options, formatted with paramfield
devalog Jul 1, 2025
95ed9a0
Small edits to formatting and descriptions
devalog Jul 1, 2025
ef5f814
Small edit to intro text
devalog Jul 1, 2025
1148090
Small edit to heading text
devalog Jul 1, 2025
5448d5e
delete some irrelevant flags
devalog Jul 3, 2025
c53665a
delete more irrelevant options
devalog Jul 3, 2025
743fcb2
delete more irrelevant options
devalog Jul 3, 2025
f6d310d
delete deprecated section
devalog Jul 3, 2025
3b89c97
delete outputEsm flag
devalog Jul 3, 2025
e136086
delete allowCustomFetcher flag
devalog Jul 3, 2025
ec3e8de
remove dynamic snippets heading
devalog Jul 3, 2025
467cd1d
add description to shouldGenerateWebsocketClients
devalog Jul 3, 2025
cf7b063
add description for extraPeerDependencies
devalog Jul 3, 2025
d879fba
add description for extraPeerDependenciesMeta
devalog Jul 3, 2025
21619d7
add description for packagePath
devalog Jul 3, 2025
ff44678
modify description for noOptionalProperties
devalog Jul 3, 2025
6c1e677
add description for packageJson
devalog Jul 3, 2025
9381dda
add description for publishToJsr
devalog Jul 3, 2025
c443c1d
remove omitUndefined
devalog Jul 3, 2025
06b4dc1
add description for streamType
devalog Jul 3, 2025
17993e9
add descriptions for fileResponseType, formDataSupport, and fetchSupport
devalog Jul 3, 2025
02ad8a8
add description for allowExtraFields
devalog Jul 3, 2025
1d518ab
update enableInlineTypes description
devalog Jul 3, 2025
0b6644c
update inlineFileProperties description
devalog Jul 3, 2025
0b59d2c
update inlinePathParameters and useBigInt
devalog Jul 3, 2025
97b4817
update noScripts and includeContentHeadersOnFileDownloadResponse
devalog Jul 3, 2025
0de0892
update noSerdeLayer
devalog Jul 3, 2025
c26aa5e
update tolerateRepublish
devalog Jul 3, 2025
76584a7
update treatUnknownAsAny
devalog Jul 3, 2025
11cacfd
added warning callout to skipResponseValidation
devalog Jul 3, 2025
bd08ff3
additional updates
devalog Jul 3, 2025
e328f5b
merge
devalog Jul 7, 2025
9b25af2
remove tolerateRepublish
devalog Jul 7, 2025
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
358 changes: 356 additions & 2 deletions fern/products/sdks/pages/typescript/configuration.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,360 @@ title: Typescript Configuration
description: Configuration options for the Fern Typescript SDK.
---

# Typescript Configuration
You can customize the behavior of the TypeScript SDK generator in `generators.yml`:

```yml {7-8}
default-group: local
groups:
local:
generators:
- name: fernapi/fern-typescript-node-sdk
version: 0.7.1
config:
useBrandedStringAliases: true
```

## SDK configuration options

<ParamField path="neverThrowErrors" type="boolean">
</ParamField>

<ParamField path="outputEsm" type="boolean" default="false">
By default, the generated TypeScript targets CommonJS. Setting to `true` targets `esnext` instead.
</ParamField>

<ParamField path="outputSourceFiles" type="boolean" default="false">
When enabled, the generator outputs raw TypeScript files. When disabled (the default), outputs `.js` and `d.ts` files.

<Note>This only applies when dumping code locally. This configuration is ignored when publishing to Github or npm._ </Note>
</ParamField>

<ParamField path="includeCredentialsOnCrossOriginRequests" type="boolean" default="false">
When enabled, [`withCredentials`](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/withCredentials) is set to `true` when making network requests.
</ParamField>

<ParamField path="bundle" type="boolean">
</ParamField>

<ParamField path="allowCustomFetcher" type="boolean" default="false">
When enabled, the generated client allows the end user to specify a custom fetcher implementation.

```typescript
const acme = new AcmeClient({
fetcher: (args) => {
...
},
});
```
</ParamField>

<ParamField path="shouldGenerateWebsocketClients" type="boolean">
</ParamField>

<ParamField path="defaultTimeoutInSeconds" type="number | 'infinity'">
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Am I understanding the TS SDK generator correct here?
If infinity, it'll use the timeout provided by the request options; otherwise, it'll fall back to 60000ms.
infinity seems kind of misleading here.
@dsinghvi

The default timeout for HTTP requests in seconds. Users can change the timeout during SDK initialization and for individual HTTP requests.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's right, i think its okay to ignore documenting RequestOptions since we already make it clear in the TS readme that it is to override the default timeout.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My understanding based on your comments is that I don't need to make any changes to this. Let me know if that's wrong though!

</ParamField>

<ParamField path="skipResponseValidation" type="boolean" default="false">
By default, the client will throw an error if the response from the server
doesn't match the expected type (based on how the response is modeled in the
Fern Definition).

If `skipResponseValidation` is set to `true`, the client will never throw if the response is misshapen. Instead, the client will log the issue using `console.warn` and return the data (casted to the expected response type).

</ParamField>

<ParamField path="extraDependencies" type="object" default="{}">
Specify extra dependencies in the generated `package.json`. This is useful
when you utilize [`.fernignore`](https://buildwithfern.com/learn/sdks/capabilities/custom-code) to
supplement the generated client with custom code.

```yaml
# generators.yml
config:
extraDependencies:
lodash: "3.0.2"
```

</ParamField>

<ParamField path="extraDevDependencies" type="object" default="{}">
Specify extra dev dependencies in the generated `package.json`.

```yaml
# generators.yml
config:
extraDevDependencies:
jest: "29.0.7"
```

<Note>Only applies when publishing to Github.</Note>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the note accurate for this option?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It isn't, @devalog lets go ahead and delete

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I copied over this note from the readme's entry for extraDevDependencies: https://github.com/fern-api/fern/tree/main/generators/typescript. @Swimburger @dsinghvi let me know if that's not right though!

</ParamField>

<ParamField path="extraPeerDependencies" type="object">
</ParamField>

<ParamField path="extraPeerDependenciesMeta" type="object">
</ParamField>

<ParamField path="treatUnknownAsAny" type="boolean" default="false">
In Fern, there's an `unknown` type that represents data that isn't knowable at runtime. When `treatUnknownAsAny` is enabled, unknown types from Fern are generated into TypeScript using `any` instead of the `unknown` type.
</ParamField>

<ParamField path="noOptionalProperties" type="boolean" default="false">
By default, Fern's `optional<>` properties will translate to optional TypeScript properties:

```yaml {4}
Person:
properties:
name: string
age: optional<integer>
```

```typescript {3}
interface Person {
name: string;
age?: number;
}
```

When `noOptionalProperties` is enabled, the generated properties are never optional. Instead, the type is generated with `| undefined`:

```typescript {3}
interface Person {
name: string;
age: number | undefined;
}
```
</ParamField>

<ParamField path="tolerateRepublish" type="boolean">
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The tolerateRepublish flag allows npm to overwrite an already-published package version, bypassing npm's default protection against republishing the same version number.

I don't know anyone using this flag, we may want to not document it, or put it at the bottom. Not sure how we're currently sorting the flags on this page.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added this description. The page is sorted by the order of the options in the config file (with deprecated/not relevant options removed entirely). If you don't think the flag is relevant, maybe removing is the best option? Can always add back in later if needed.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@dsinghvi I do think this is so uncommonly used, we could omit it to make the flag list smaller.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just removed this flag for now!

</ParamField>

<ParamField path="packageJson" type="object">
</ParamField>

<ParamField path="publishToJsr" type="boolean">
</ParamField>

<ParamField path="omitUndefined" type="boolean">
</ParamField>

<ParamField path="useLegacyExports" type="boolean">
</ParamField>

<ParamField path="streamType" type="'wrapper' | 'web'">
</ParamField>

<ParamField path="fileResponseType" type="'stream' | 'binary-response'">
</ParamField>

<ParamField path="formDataSupport" type="'Node16' | 'Node18'">
</ParamField>

<ParamField path="fetchSupport" type="'node-fetch' | 'native'">
</ParamField>

<ParamField path="packagePath" type="string">
</ParamField>

### Options relevant to dynamic snippets

<ParamField path="allowExtraFields" type="boolean">

</ParamField>

<ParamField path="enableInlineTypes" type="boolean">
</ParamField>

<ParamField path="inlineFileProperties" type="boolean">
</ParamField>

<ParamField path="inlinePathParameters" type="boolean">
</ParamField>

<ParamField path="namespaceExport" type="string">
By default, names are based on the organization and API names in the Fern Definition:

```typescript
import { AcmeApi, AcmeApiClient } from "@acme/node";
```

`namespaceExport` customizes the exported namespace and client names:

```yaml
# generators.yml
config:
namespaceExport: Acme
```

```typescript
import { Acme, AcmeClient } from "@acme/node";
```

</ParamField>

<ParamField path="noSerdeLayer" type="boolean" default="false">
By default, the generated client includes a layer for serializing requests and deserializing responses. This has three benefits:

1. The client validates requests and response at runtime (client-side).

1. The client can support complex types like `Date` and `Set`.

1. The generated types can stray from the wire/JSON representation to be more
idiomatic. For example, when `noSerdeLayer` is disabled, all properties are `camelCase`,
even if the server is expecting `snake_case`.

When `noSerdeLayer` is enabled, no serialization/deserialization code is generated. The client uses `JSON.parse()` and `JSON.stringify()` instead of the default Serde layer.


</ParamField>

<ParamField path="private" type="boolean">
</ParamField>

<ParamField path="requireDefaultEnvironment" type="boolean" default="false">
When enabled, the generated client doesn't allow the user to specify a server URL. When disabled (the default), the generated client includes an option to override the server URL:

```typescript
const acme = new AcmeClient({
environment: "localhost:8080"
});
```
</ParamField>

<ParamField path="retainOriginalCasing" type="boolean" default="false">
When enabled, property names in the generated code retain their original casing from the API definition instead of being converted to camelCase.

```yaml
# generators.yml
config:
retainOriginalCasing: true
```

**Example with OpenAPI input:**
```yaml {7, 9}
# OpenAPI schema
components:
schemas:
User:
type: object
properties:
user_id:
type: string
display_name:
type: string
```

Generated TypeScript with `retainOriginalCasing: true`:
```typescript {2-3}
export interface User {
user_id: string;
display_name: string;
}
```

Generated TypeScript with default settings (`retainOriginalCasing: false`):
```typescript {2-3}
export interface User {
userId: string;
displayName: string;
}
```

</ParamField>

<ParamField path="useBigInt" type="boolean">
</ParamField>

<ParamField path="useBrandedStringAliases" type="boolean" default="false">

When `useBrandedStringAliases` is disabled (the default), string aliases are generated as
normal TypeScript aliases:

```typescript
// generated code

export type MyString = string;

export type OtherString = string;
```
When `useBrandedStringAliases` is enabled, string aliases are generated as branded strings. This makes each alias feel like its own type and improves compile-time safety.

```yaml
# fern definition

types:
MyString: string
OtherString: string
```

```typescript
// generated code

export type MyString = string & { __MyString: void };
export const MyString = (value: string): MyString => value as MyString;

export type OtherString = string & { __OtherString: void };
export const OtherString = (value: string): OtherString => value as OtherString;
```

```typescript
// consuming the generated type

function printMyString(s: MyString): void {
console.log("MyString: " + s);
}

// doesn't compile, "foo" is not assignable to MyString
printMyString("foo");

const otherString = OtherString("other-string");
// doesn't compile, otherString is not assignable to MyString
printMyString(otherString);

// compiles
const myString = MyString("my-string");
printMyString(myString);
```

</ParamField>

<ParamField path="neverThrowErrors" type="boolean" default="false">
When enabled, the client doesn't throw errors when a non-200 response is received from the server. Instead, the response is wrapped in an [`ApiResponse`](packages/core-utilities/fetcher/src/APIResponse.ts).

```typescript
const response = await client.callEndpoint(...);
if (response.ok) {
console.log(response.body)
} else {
console.error(respons.error)
}
```
</ParamField>

### Beta options

<ParamField path="includeContentHeadersOnFileDownloadResponse" type="boolean">
</ParamField>

<ParamField path="includeUtilsOnUnionMembers" type="boolean">
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm kinda struggling with this one

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I could just remove this entirely, or leave it in with no description for now?

</ParamField>

<ParamField path="includeOtherInUnionTypes" type="boolean">
</ParamField>

<ParamField path="generateWireTests" type="boolean">
</ParamField>

<ParamField path="noScripts" type="boolean">
</ParamField>

### Deprecated options

<ParamField path="timeoutInSeconds" type="number | 'infinity'" deprecated={true}>
The default timeout for network requests. In the generated client, this can be overridden at the request level.
</ParamField>

<ParamField path="includeApiReference" type="boolean" deprecated={true}>
</ParamField>

Discover how to configure the Fern Typescript SDK for your project.