Skip to content

Add AsyncFunction types - #1496

Open
zfaustk wants to merge 4 commits into
sindresorhus:mainfrom
zfaustk:add-async-function-types
Open

zfaustk wants to merge 4 commits into
sindresorhus:mainfrom
zfaustk:add-async-function-types

Conversation

@zfaustk

@zfaustk zfaustk commented Aug 12, 2026

Copy link
Copy Markdown

Closes #121

This adds the three connected Basic function types from the final issue specification:

  • AsyncFunction<Arguments, ReturnValue> for a reusable asynchronous signature;
  • AnyAsyncFunction for an erased asynchronous function constraint;
  • AnyFunction for an erased sync-or-async function constraint.

The definitions follow the names, defaults, and any edge-case decision discussed in #121. They live alongside the existing class and constructor types in source/basic.d.ts, with README entries and examples.

Tests cover generic arguments and return values, defaults, any, rejection of synchronous functions by AnyAsyncFunction, acceptance of synchronous and asynchronous functions by AnyFunction, and a never parameter.

Validation:

  • npx tsd --files test-d/async-function.ts
  • npm run test:tsd
  • npm run test:tsc
  • npm run test:xo
  • npm run test:linter

Codex assisted with checking the type edge cases, naming, documentation, examples, and test coverage against the upstream discussion and repository conventions.

## Context
- Principle: AnyAsyncFunction must constrain Promise-returning functions without erasing their callable signatures.
- Why: Signature-preserving examples and discriminating type boundaries keep the public constraint safe to copy.

## Key Deltas
- AnyAsyncFunction documentation: zero-argument invocation after signature erasure -> generic registration that retains parameters and return type; why: prevent examples from implying unsafe calls. Key refs: source/basic.d.ts:62
- AnyAsyncFunction type tests: zero-argument async and sync pair -> required, never, structural Promise, and synchronous boundaries; why: distinguish the accepted structural contract without changing the type. Key refs: test-d/async-function.ts:13

## Verification
- Result: passed
Comment thread source/basic.d.ts Outdated
@category Basic
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export type AnyFunction = (...arguments_: readonly any[]) => any;

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Suggested change
export type AnyFunction = (...arguments_: readonly any[]) => any;
export type AnyFunction = (...arguments_: readonly any[]) => unknown;

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Updated AnyFunction to return unknown as suggested.

Comment thread test-d/async-function.ts

expectAssignable<AnyFunction>((value: never) => value);
expectAssignable<AnyFunction>(async () => 'value');
expectAssignable<AnyFunction>(() => 'value');

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

I would add a few more tests:

// `Arguments` is enforced.
expectError(asyncFunction());
expectError(asyncFunction(123));

// `ReturnValue` is enforced.
expectNotAssignable<AsyncFunction<[value: string], number>>(
	async (value: string) => value,
);

// Defaults accept arbitrary arguments.
expectType<Promise<unknown>>(defaultAsyncFunction('value', 123));

// Erased functions remain callable with an unknown result.
declare const anyFunction: AnyFunction;
expectType<unknown>(anyFunction('value', 123));

declare const erasedAsyncFunction: AnyAsyncFunction;
expectType<Promise<unknown>>(erasedAsyncFunction('value', 123));

// Ordinary required parameters are supported.
expectAssignable<AnyFunction>((value: string) => value);

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Added these cases, including direct invalid-call checks for the argument constraints. The full npm test suite passes locally.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Proposal: AsyncFunction

2 participants