Skip to content

Parameters does not work in JS files unless a @param has been explicitly definedΒ #61172

@RobertAKARobin

Description

@RobertAKARobin

πŸ”Ž Search Terms

paramaters param

πŸ•— Version & Regression Information

  • This is the behavior in every version I tried, and I reviewed the FAQ for entries about Parameters

⏯ Playground Link

https://www.typescriptlang.org/play/?strictNullChecks=true&filetype=js#code/GYVwdgxgLglg9mABAJwKYAdUEMoAoBQAkAPQBUpiAAlAJ6aIDeAzlMjGAOYC+ipxiAW1RMmWDqgA0RMhWp1UjMCAEAjVMh59EsIUykBKRkTRQQyJAEFkyLDVw7h+gHTAYAGze5do8c4BWcOy4AAaIwfoA3Phc+PgyVLT0DAAKWDZCUOpMADyJqHDAKBjYUAB8ANoADAC6msT4EAgsgsI+CgC8YQAWqB5wwVFx5AnyjKnpqJnIOXkFRZg4FQCMtbz1jWDNDkyInQDMUUA

πŸ’» Code

function repeat(
	/** @type {string} */ message,
	/** @type {number} */ times,
) {
	return Array(times).fill(message).join(` `);
}

/** @type {Parameters<typeof repeat>[0]} */
const message = `hello`; // Error: Type '"hello"' is not assignable to type 'never'. (ts2322)

/** @type {Parameters<typeof repeat>[1]} */
const times = 3; // Error: Type '3' is not assignable to type 'never'. (ts2322)

πŸ™ Actual behavior

Parameters<typeof repeat> coalesces into type never.

πŸ™‚ Expected behavior

Parameters<typeof repeat> coalesces into type [message: string, times: number].

Additional information about the issue

This error occurs if a function's arguments are defined with @type, but not if they're explicitly defined with @param. For example, this works as expected:

/**
 * @param {string} message
 * @param {number} times
 */
function repeat(message, times) {
	return Array(times).fill(message).join(` `);
}

/** @type {Parameters<typeof repeat>[0]} */
export const myMessage = `hello`; // No error

/** @type {Parameters<typeof repeat>[1]} */
export const myTimes = 3; // No error

However, it is unreasonable to always require that @params be explicitly written for every function, e.g. when writing a callback that already has a defined shape.

This utility type serves as a workaround:

export type Params<Target extends (...args: any) => any> =
	Target extends (arg0: infer Arg0, arg1: infer Arg1, arg2: infer Arg2) => any  // Can add more args if we need them
	? [Arg0, Arg1, Arg2]
	: never;
function repeat(
	/** @type {string} */message,
	/** @type {number} */times,
) {
	return Array(times).fill(message).join(` `);
}

/** @type {Params<typeof repeat>[0]} */
export const myMessage = `hello`; // No error

/** @type {Params<typeof repeat>[1]} */
export const myTimes = 3; // No error

Metadata

Metadata

Assignees

Labels

BugA bug in TypeScript

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions