Skip to content

Commit c55a396

Browse files
author
Piet van Agtmaal
committed
Avoid adding undefined to the index signature for additionalProperties
1 parent 6899a51 commit c55a396

File tree

9 files changed

+618
-571
lines changed

9 files changed

+618
-571
lines changed

.changeset/ninety-tips-sip.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"openapi-typescript": minor
3+
---
4+
5+
Avoid adding a undefined union to additionProperties

docs/src/content/docs/advanced.md

+4
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,10 @@ However, APIs are language-agnostic, and may contain a different syntax style fr
182182
183183
Instead, treat “consistency” in a more holistic sense, recognizing that preserving the API schema as-written is better than adhering to language-specific style conventions.
184184
185+
### Enable `noUncheckedIndexAccess` in your tsconfig.json
186+
187+
openapi-typescript generates a `Record` for `additionalProperties` and tries to avoid adding a `undefined` union to the index signature. However, this may result in unsafe property access in TypeScript, **unless** the compiler flag `noUncheckedIndexAccess` is set. If set, TypeScript will error when you try to access a property that might not be set.
188+
185189
### Be specific in your schema
186190
187191
openapi-typescript will **never produce an `any` type**. Anything not explicated in your schema may as well not exist. For that reason, always be as specific as possible. Here’s how to get the most out of `additionalProperties`:

packages/openapi-typescript/examples/digital-ocean-api.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -11958,7 +11958,7 @@ export interface external {
1195811958
* }
1195911959
*/
1196011960
metric: {
11961-
[key: string]: string | undefined;
11961+
[key: string]: string;
1196211962
};
1196311963
/**
1196411964
* @example [

packages/openapi-typescript/examples/github-api-next.ts

+31-31
Original file line numberDiff line numberDiff line change
@@ -12220,7 +12220,7 @@ export interface components {
1222012220
language?: string;
1222112221
raw_url?: string;
1222212222
size?: number;
12223-
} | undefined;
12223+
};
1222412224
};
1222512225
public: boolean;
1222612226
/** Format: date-time */
@@ -12360,7 +12360,7 @@ export interface components {
1236012360
language?: string;
1236112361
raw_url?: string;
1236212362
size?: number;
12363-
} | undefined;
12363+
};
1236412364
};
1236512365
public: boolean;
1236612366
/** Format: date-time */
@@ -12386,15 +12386,15 @@ export interface components {
1238612386
git_push_url?: string;
1238712387
html_url?: string;
1238812388
files?: {
12389-
[key: string]: ({
12389+
[key: string]: {
1239012390
filename?: string;
1239112391
type?: string;
1239212392
language?: string;
1239312393
raw_url?: string;
1239412394
size?: number;
1239512395
truncated?: boolean;
1239612396
content?: string;
12397-
} | null) | undefined;
12397+
} | null;
1239812398
};
1239912399
public?: boolean;
1240012400
created_at?: string;
@@ -13807,13 +13807,13 @@ export interface components {
1380713807
/** @description Permissions requested, categorized by type of permission. */
1380813808
permissions: {
1380913809
organization?: {
13810-
[key: string]: string | undefined;
13810+
[key: string]: string;
1381113811
};
1381213812
repository?: {
13813-
[key: string]: string | undefined;
13813+
[key: string]: string;
1381413814
};
1381513815
other?: {
13816-
[key: string]: string | undefined;
13816+
[key: string]: string;
1381713817
};
1381813818
};
1381913819
/** @description Date and time when the request for access was created. */
@@ -13843,13 +13843,13 @@ export interface components {
1384313843
/** @description Permissions requested, categorized by type of permission. */
1384413844
permissions: {
1384513845
organization?: {
13846-
[key: string]: string | undefined;
13846+
[key: string]: string;
1384713847
};
1384813848
repository?: {
13849-
[key: string]: string | undefined;
13849+
[key: string]: string;
1385013850
};
1385113851
other?: {
13852-
[key: string]: string | undefined;
13852+
[key: string]: string;
1385313853
};
1385413854
};
1385513855
/** @description Date and time when the fine-grained personal access token was approved to access the organization. */
@@ -17048,7 +17048,7 @@ export interface components {
1704817048
* @description User-defined metadata to store domain-specific information limited to 8 keys with scalar values.
1704917049
*/
1705017050
metadata: {
17051-
[key: string]: (null | string | number | boolean) | undefined;
17051+
[key: string]: null | string | number | boolean;
1705217052
};
1705317053
dependency: {
1705417054
/** @description Package-url (PURL) of dependency. See https://github.com/package-url/purl-spec for more details. */
@@ -17077,7 +17077,7 @@ export interface components {
1707717077
metadata?: components["schemas"]["metadata"];
1707817078
/** @description A collection of resolved package dependencies. */
1707917079
resolved?: {
17080-
[key: string]: components["schemas"]["dependency"] | undefined;
17080+
[key: string]: components["schemas"]["dependency"];
1708117081
};
1708217082
};
1708317083
/**
@@ -17111,7 +17111,7 @@ export interface components {
1711117111
metadata?: components["schemas"]["metadata"];
1711217112
/** @description A collection of package manifests, which are a collection of related dependencies declared in a file or representing a logical group of dependencies. */
1711317113
manifests?: {
17114-
[key: string]: components["schemas"]["manifest"] | undefined;
17114+
[key: string]: components["schemas"]["manifest"];
1711517115
};
1711617116
/**
1711717117
* Format: date-time
@@ -18250,7 +18250,7 @@ export interface components {
1825018250
* @description Language
1825118251
*/
1825218252
language: {
18253-
[key: string]: number | undefined;
18253+
[key: string]: number;
1825418254
};
1825518255
/**
1825618256
* License Content
@@ -20594,37 +20594,37 @@ export interface components {
2059420594
/** @description New requested permissions, categorized by type of permission. */
2059520595
permissions_added: {
2059620596
organization?: {
20597-
[key: string]: string | undefined;
20597+
[key: string]: string;
2059820598
};
2059920599
repository?: {
20600-
[key: string]: string | undefined;
20600+
[key: string]: string;
2060120601
};
2060220602
other?: {
20603-
[key: string]: string | undefined;
20603+
[key: string]: string;
2060420604
};
2060520605
};
2060620606
/** @description Requested permissions that elevate access for a previously approved request for access, categorized by type of permission. */
2060720607
permissions_upgraded: {
2060820608
organization?: {
20609-
[key: string]: string | undefined;
20609+
[key: string]: string;
2061020610
};
2061120611
repository?: {
20612-
[key: string]: string | undefined;
20612+
[key: string]: string;
2061320613
};
2061420614
other?: {
20615-
[key: string]: string | undefined;
20615+
[key: string]: string;
2061620616
};
2061720617
};
2061820618
/** @description Permissions requested, categorized by type of permission. This field incorporates `permissions_added` and `permissions_upgraded`. */
2061920619
permissions_result: {
2062020620
organization?: {
20621-
[key: string]: string | undefined;
20621+
[key: string]: string;
2062220622
};
2062320623
repository?: {
20624-
[key: string]: string | undefined;
20624+
[key: string]: string;
2062520625
};
2062620626
other?: {
20627-
[key: string]: string | undefined;
20627+
[key: string]: string;
2062820628
};
2062920629
};
2063020630
/**
@@ -37960,12 +37960,12 @@ export interface components {
3796037960
};
3796137961
platform?: string;
3796237962
metadata?: {
37963-
[key: string]: string | undefined;
37963+
[key: string]: string;
3796437964
};
3796537965
repo?: string;
37966-
dependencies?: ({
37967-
[key: string]: string | undefined;
37968-
})[];
37966+
dependencies?: {
37967+
[key: string]: string;
37968+
}[];
3796937969
commit_oid?: string;
3797037970
};
3797137971
/** package published event */
@@ -78906,7 +78906,7 @@ export interface operations {
7890678906
200: {
7890778907
content: {
7890878908
"application/json": {
78909-
[key: string]: string | undefined;
78909+
[key: string]: string;
7891078910
};
7891178911
};
7891278912
};
@@ -79078,7 +79078,7 @@ export interface operations {
7907879078
[key: string]: {
7907979079
/** @description Content of the file */
7908079080
content: string;
79081-
} | undefined;
79081+
};
7908279082
};
7908379083
public?: boolean | ("true" | "false");
7908479084
};
@@ -79215,12 +79215,12 @@ export interface operations {
7921579215
* To delete a file, set the whole file to null. For example: `hello.py : null`.
7921679216
*/
7921779217
files?: {
79218-
[key: string]: (({
79218+
[key: string]: ({
7921979219
/** @description The new content of the file. */
7922079220
content?: string;
7922179221
/** @description The new filename for the file. */
7922279222
filename?: string | null;
79223-
}) | null) | undefined;
79223+
}) | null;
7922479224
};
7922579225
}) | null;
7922679226
};

0 commit comments

Comments
 (0)