Skip to content

feat(javascript): add exactOptionalPropertyTypes to tsconfig #4935

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Jun 9, 2025
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
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export function createIterablePromise<TResponse>({
error,
timeout = (): number => 0,
}: CreateIterablePromise<TResponse>): Promise<TResponse> {
const retry = (previousResponse?: TResponse): Promise<TResponse> => {
const retry = (previousResponse?: TResponse | undefined): Promise<TResponse> => {
Copy link
Collaborator

Choose a reason for hiding this comment

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

exactOptionalPropertyTypes is only for type or interface, you don't need to change the parameters in functions

Copy link
Member Author

Choose a reason for hiding this comment

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

I prefer to stay consistent consider I don't really know what's the upstream impact of this, it added a bit more of work but at least there should be no surprise

return new Promise<TResponse>((resolve, reject) => {
func(previousResponse)
.then(async (response) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@ import type { Logger } from '../types/logger';

export function createNullLogger(): Logger {
return {
debug(_message: string, _args?: any): Promise<void> {
debug(_message: string, _args?: any | undefined): Promise<void> {
return Promise.resolve();
},
info(_message: string, _args?: any): Promise<void> {
info(_message: string, _args?: any | undefined): Promise<void> {
return Promise.resolve();
},
error(_message: string, _args?: any): Promise<void> {
error(_message: string, _args?: any | undefined): Promise<void> {
return Promise.resolve();
},
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,12 +76,12 @@ export type DetailedErrorWithMessage = {
export type DetailedErrorWithTypeID = {
id: string;
type: string;
name?: string;
name?: string | undefined;
};

export type DetailedError = {
code: string;
details?: DetailedErrorWithMessage[] | DetailedErrorWithTypeID[];
details?: DetailedErrorWithMessage[] | DetailedErrorWithTypeID[] | undefined;
};

// DetailedApiError is only used by the ingestion client to return more informative error, other clients will use ApiClient.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ export function serializeData(request: Request, requestOptions: RequestOptions):
export function serializeHeaders(
baseHeaders: Headers,
requestHeaders: Headers,
requestOptionsHeaders?: Headers,
requestOptionsHeaders?: Headers | undefined,
): Headers {
const headers: Headers = {
Accept: 'application/json',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ export type Cache = {
get: <TValue>(
key: Record<string, any> | string,
defaultValue: () => Promise<TValue>,
events?: CacheEvents<TValue>,
events?: CacheEvents<TValue> | undefined,
) => Promise<TValue>;

/**
Expand Down Expand Up @@ -35,7 +35,7 @@ export type MemoryCacheOptions = {
/**
* If keys and values should be serialized using `JSON.stringify`.
*/
serializable?: boolean;
serializable?: boolean | undefined;
};

export type BrowserLocalStorageOptions = {
Expand All @@ -47,12 +47,12 @@ export type BrowserLocalStorageOptions = {
/**
* The time to live for each cached item in seconds.
*/
timeToLive?: number;
timeToLive?: number | undefined;

/**
* The native local storage implementation.
*/
localStorage?: Storage;
localStorage?: Storage | undefined;
};

export type BrowserLocalStorageCacheItem = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export type CreateClientOptions = Omit<TransporterOptions, OverriddenTransporter
Partial<Pick<TransporterOptions, OverriddenTransporterOptions>> & {
appId: string;
apiKey: string;
authMode?: AuthMode;
authMode?: AuthMode | undefined;
algoliaAgents: AlgoliaAgentOptions[];
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export type CreateIterablePromise<TResponse> = IterableOptions<TResponse> & {
*
* The `previousResponse` parameter (`undefined` on the first call) allows you to build your request with incremental logic, to iterate on `page` or `cursor` for example.
*/
func: (previousResponse?: TResponse) => Promise<TResponse>;
func: (previousResponse?: TResponse | undefined) => Promise<TResponse>;

/**
* The validator function. It receive the resolved return of the API call.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export type Host = {
/**
* The port of the host URL.
*/
port?: number;
port?: number | undefined;
};

export type StatefulHost = Host & {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,15 @@ export type Logger = {
/**
* Logs debug messages.
*/
debug: (message: string, args?: any) => Promise<void>;
debug: (message: string, args?: any | undefined) => Promise<void>;

/**
* Logs info messages.
*/
info: (message: string, args?: any) => Promise<void>;
info: (message: string, args?: any | undefined) => Promise<void>;

/**
* Logs error messages.
*/
error: (message: string, args?: any) => Promise<void>;
error: (message: string, args?: any | undefined) => Promise<void>;
};
Original file line number Diff line number Diff line change
Expand Up @@ -14,18 +14,18 @@ export type Request = {
*/
path: string;
queryParameters: QueryParameters;
data?: Array<Record<string, any>> | Record<string, any>;
data?: Array<Record<string, any>> | Record<string, any> | undefined;
headers: Headers;
/**
* If the given request should persist on the cache. Keep in mind,
* that some methods may have this option enabled by default.
*/
cacheable?: boolean;
cacheable?: boolean | undefined;
/**
* Some POST methods in the Algolia REST API uses the `read` transporter.
* This information is defined at the spec level.
*/
useReadTransporter?: boolean;
useReadTransporter?: boolean | undefined;
};

export type EndRequest = Pick<Request, 'headers' | 'method'> & {
Expand All @@ -41,7 +41,7 @@ export type EndRequest = Pick<Request, 'headers' | 'method'> & {
* The response timeout, in milliseconds.
*/
responseTimeout: number;
data?: string;
data?: string | undefined;
};

export type Response = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,25 +9,25 @@ export type RequestOptions = Pick<Request, 'cacheable'> & {
* the given timeout will be applied. But the transporter layer may
* increase this timeout if there is need for it.
*/
timeouts?: Partial<Timeouts>;
timeouts?: Partial<Timeouts> | undefined;

/**
* Custom headers for the request. This headers are
* going to be merged the transporter headers.
*/
headers?: Headers;
headers?: Headers | undefined;

/**
* Custom query parameters for the request. This query parameters are
* going to be merged the transporter query parameters.
*/
queryParameters?: QueryParameters;
queryParameters?: QueryParameters | undefined;

/**
* Custom data for the request. This data is
* going to be merged the transporter data.
*/
data?: Array<Record<string, any>> | Record<string, any>;
data?: Array<Record<string, any>> | Record<string, any> | undefined;
};

export type StackFrame = {
Expand All @@ -46,7 +46,7 @@ export type AlgoliaAgentOptions = {
/**
* The version. Usually the integration version.
*/
version?: string;
version?: string | undefined;
};

export type AlgoliaAgent = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,23 @@ import { LogLevelEnum } from '@algolia/client-common';

export function createConsoleLogger(logLevel: LogLevelType): Logger {
return {
debug(message: string, args?: any): Readonly<Promise<void>> {
debug(message: string, args?: any | undefined): Readonly<Promise<void>> {
if (LogLevelEnum.Debug >= logLevel) {
console.debug(message, args);
}

return Promise.resolve();
},

info(message: string, args?: any): Readonly<Promise<void>> {
info(message: string, args?: any | undefined): Readonly<Promise<void>> {
if (LogLevelEnum.Info >= logLevel) {
console.info(message, args);
}

return Promise.resolve();
},

error(message: string, args?: any): Readonly<Promise<void>> {
error(message: string, args?: any | undefined): Readonly<Promise<void>> {
console.error(message, args);

return Promise.resolve();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ function getErrorMessage(error: unknown, abortContent: string): string {
}

export type FetchRequesterOptions = {
readonly requesterOptions?: RequestInit;
readonly requesterOptions?: RequestInit | undefined;
};

export function createFetchRequester({ requesterOptions = {} }: FetchRequesterOptions = {}): Requester {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ export type EchoResponse = Omit<EndRequest, 'data'> &
Pick<Request, 'data' | 'path'> & {
host: string;
algoliaAgent: string;
searchParams?: Record<string, string>;
searchParams?: Record<string, string> | undefined;
};

type BasicURL = {
Expand All @@ -15,7 +15,7 @@ type BasicURL = {

export type EchoRequesterParams = {
getURL: (url: string) => BasicURL;
status?: number;
status?: number | undefined;
};

function getUrlParams({
Expand Down
7 changes: 4 additions & 3 deletions clients/algoliasearch-client-javascript/tsconfig.json
Original file line number Diff line number Diff line change
@@ -1,24 +1,25 @@
{
"compilerOptions": {
"allowJs": false,
"verbatimModuleSyntax": true,
"allowSyntheticDefaultImports": true,
"declaration": true,
"esModuleInterop": true,
"exactOptionalPropertyTypes": true,
"lib": ["dom", "esnext", "dom.iterable", "scripthost"],
"module": "esnext",
"moduleResolution": "node",
"noImplicitAny": true,
"noImplicitThis": true,
"noImplicitOverride": true,
"noImplicitThis": true,
"noLib": false,
"noUnusedLocals": true,
"outDir": "dist",
"removeComments": false,
"sourceMap": true,
"strict": true,
"target": "esnext",
"types": ["node"]
"types": ["node"],
"verbatimModuleSyntax": true
},
"include": ["packages/**/*.ts"],
"exclude": ["dist", "node_modules"]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ export type Algoliasearch = SearchClient & {
* @param saveObjects.waitForTasks - Whether or not we should wait until every `batch` tasks has been processed, this operation may slow the total execution time of this method but is more reliable.
* @param requestOptions - The requestOptions to send along with the query, they will be forwarded to the `batch` method and merged with the transporter requestOptions.
*/
saveObjectsWithTransformation: (options: SaveObjectsOptions, requestOptions?: RequestOptions) => Promise<WatchResponse>;
saveObjectsWithTransformation: (options: SaveObjectsOptions, requestOptions?: RequestOptions | undefined) => Promise<WatchResponse>;

/**
* Helper: Similar to the `partialUpdateObjects` method but requires a Push connector (https://www.algolia.com/doc/guides/sending-and-managing-data/send-and-update-your-data/connectors/push/) to be created first, in order to transform records before indexing them to Algolia. The `region` must have been passed to the client instantiation method.
Expand All @@ -56,21 +56,21 @@ export type Algoliasearch = SearchClient & {
* @param partialUpdateObjects.waitForTasks - Whether or not we should wait until every `batch` tasks has been processed, this operation may slow the total execution time of this method but is more reliable.
* @param requestOptions - The requestOptions to send along with the query, they will be forwarded to the `getTask` method and merged with the transporter requestOptions.
*/
partialUpdateObjectsWithTransformation: (options: PartialUpdateObjectsOptions, requestOptions?: RequestOptions) => Promise<WatchResponse>;
partialUpdateObjectsWithTransformation: (options: PartialUpdateObjectsOptions, requestOptions?: RequestOptions | undefined) => Promise<WatchResponse>;
};

export type TransformationOptions = {
// When provided, a second transporter will be created in order to leverage the `*WithTransformation` methods exposed by the Push connector (https://www.algolia.com/doc/guides/sending-and-managing-data/send-and-update-your-data/connectors/push/).
transformation?: {
// The region of your Algolia application ID, used to target the correct hosts of the transformation service.
region: IngestionRegion;
};
} | undefined;
};

export function algoliasearch(
appId: string,
apiKey: string,
options?: ClientOptions & TransformationOptions,
options?: ClientOptions & TransformationOptions | undefined,
): Algoliasearch {
if (!appId || typeof appId !== 'string') {
throw new Error('`appId` is missing.');
Expand Down
4 changes: 2 additions & 2 deletions templates/javascript/clients/api-single.mustache
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ export function create{{#lambda.titlecase}}{{clientName}}{{/lambda.titlecase}}({
* @param segment - The algolia agent (user-agent) segment to add.
* @param version - The version of the agent.
*/
addAlgoliaAgent(segment: string, version?: string): void {
addAlgoliaAgent(segment: string, version?: string | undefined): void {
transporter.algoliaAgent.add({ segment, version });
},

Expand Down Expand Up @@ -182,4 +182,4 @@ export function create{{#lambda.titlecase}}{{clientName}}{{/lambda.titlecase}}({
};
}

{{/operations}}
{{/operations}}
Loading