From c20c17459e84a8122a941197519e8a14658cf6ce Mon Sep 17 00:00:00 2001 From: Erik Golinelli Date: Thu, 16 May 2024 11:05:06 +0200 Subject: [PATCH 1/3] adds strict type definitions to sprintf --- packages/sprintf/.gitignore | 1 + packages/sprintf/index.js | 25 +++++++++---------------- packages/sprintf/types/index.d.ts | 26 ++++++++++++++++++++++++++ 3 files changed, 36 insertions(+), 16 deletions(-) create mode 100644 packages/sprintf/.gitignore create mode 100644 packages/sprintf/types/index.d.ts diff --git a/packages/sprintf/.gitignore b/packages/sprintf/.gitignore new file mode 100644 index 0000000..6377d49 --- /dev/null +++ b/packages/sprintf/.gitignore @@ -0,0 +1 @@ +!types/* diff --git a/packages/sprintf/index.js b/packages/sprintf/index.js index 31ca82f..e0f0836 100644 --- a/packages/sprintf/index.js +++ b/packages/sprintf/index.js @@ -53,26 +53,19 @@ var PATTERN = * sprintf( 'Hello %s!', 'world' ); * // ⇒ 'Hello world!' * ``` - * - * @param {string} string printf format string - * @param {...string|string[]|Object} [args] String arguments. + * @template {string} T + * @param {T} string - string printf format string + * @param {import('./types/index.d').SprintfArgs|import('./types/index.d').SprintfArgs[]|undefined} args String arguments. * * @return {string} Formatted string. */ -export default function sprintf(string, args) { - var i; +export default function sprintf(string, ...args) { + var i = 0; - if (!Array.isArray(args)) { - // Construct a copy of arguments from index one, used for replace - // function placeholder substitution. - args = new Array(arguments.length - 1); - for (i = 1; i < arguments.length; i++) { - args[i - 1] = arguments[i]; - } + if (Array.isArray(args[0])) { + args = /** @type {import('./types/index.d').SprintfArgs[]} */ args[0]; } - i = 1; - return string.replace(PATTERN, function () { var index, name, precision, type, value; @@ -89,14 +82,14 @@ export default function sprintf(string, args) { // Asterisk precision determined by peeking / shifting next argument. if (precision === '*') { - precision = args[i - 1]; + precision = args[i]; i++; } if (name === undefined) { // If not a positional argument, use counter value. if (index === undefined) { - index = i; + index = i + 1; } i++; diff --git a/packages/sprintf/types/index.d.ts b/packages/sprintf/types/index.d.ts new file mode 100644 index 0000000..8e0c2d0 --- /dev/null +++ b/packages/sprintf/types/index.d.ts @@ -0,0 +1,26 @@ +type Specifiers = { + 's': string, + 'd': number, + 'b': boolean, + 'D': Date +}; +type S = keyof Specifiers; + +type ExtractNamedPlaceholders = + T extends `${any}%(${infer Key})${infer Spec}${infer Rest}` + ? Spec extends S + ? { [K in Key]: Specifiers[Spec]} & ExtractNamedPlaceholders + : never + : {}; + +type ExtractUnnamedPlaceholders = + T extends `${any}%${infer Spec}${infer Rest}` + ? Spec extends S + ? [Specifiers[Spec], ...ExtractUnnamedPlaceholders] + : never + : []; + +export type SprintfArgs = + ExtractUnnamedPlaceholders extends never + ? [values: ExtractNamedPlaceholders] + : ExtractUnnamedPlaceholders; From 91c83e25c73d83b0537e7d39837ecd50835579f0 Mon Sep 17 00:00:00 2001 From: Erik Golinelli Date: Thu, 16 May 2024 15:10:02 +0200 Subject: [PATCH 2/3] types updated to match the supported specifiers (%d %f and %s) --- packages/sprintf/index.js | 2 +- packages/sprintf/types/index.d.ts | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/packages/sprintf/index.js b/packages/sprintf/index.js index e0f0836..7d9799e 100644 --- a/packages/sprintf/index.js +++ b/packages/sprintf/index.js @@ -55,7 +55,7 @@ var PATTERN = * ``` * @template {string} T * @param {T} string - string printf format string - * @param {import('./types/index.d').SprintfArgs|import('./types/index.d').SprintfArgs[]|undefined} args String arguments. + * @param {import('./types/index.d').SprintfArgs|import('./types/index.d').SprintfArgs[]} args String arguments. * * @return {string} Formatted string. */ diff --git a/packages/sprintf/types/index.d.ts b/packages/sprintf/types/index.d.ts index 8e0c2d0..ed926a6 100644 --- a/packages/sprintf/types/index.d.ts +++ b/packages/sprintf/types/index.d.ts @@ -1,8 +1,7 @@ type Specifiers = { 's': string, 'd': number, - 'b': boolean, - 'D': Date + 'f': number }; type S = keyof Specifiers; From f3923f985606bc0767f8b180f51495b91ce753b0 Mon Sep 17 00:00:00 2001 From: Erik Golinelli Date: Fri, 17 May 2024 12:32:52 +0200 Subject: [PATCH 3/3] includes types/index.d.ts to the published files --- packages/sprintf/package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/sprintf/package.json b/packages/sprintf/package.json index 04d3653..85bb1f5 100644 --- a/packages/sprintf/package.json +++ b/packages/sprintf/package.json @@ -31,6 +31,7 @@ "files": [ "index.js", "index.d.ts", + "types/index.d.ts", "build", "dist" ],