From c64895334e104ccc6cc60e872595e6338fbcdfa9 Mon Sep 17 00:00:00 2001 From: Iddar Olivares Date: Wed, 20 Nov 2024 15:06:35 -0600 Subject: [PATCH] types: improve type inference for cx concatenation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit • Return exact string literal types instead of plain string • Handle conditional types and unions correctly • No runtime changes or performance impact Before: cx("foo", "bar") → type: string cx("foo", null, "bar") → type: never After: cx("foo", "bar") → type: "foo bar" cx("foo", null, "bar") → type: "foo bar" --- src/index.ts | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/src/index.ts b/src/index.ts index ee6a71d..db3fa44 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,11 +1,35 @@ export type ClassName = string | boolean | null | undefined; +type FilterStrings = T extends readonly [ + infer F, + ...infer R, +] + ? F extends string + ? [F, ...FilterStrings] + : FilterStrings + : []; + +type JoinStrings = T extends readonly [ + infer F, + ...infer R, +] + ? F extends string + ? R extends readonly string[] + ? R["length"] extends 0 + ? F + : `${F} ${JoinStrings}` + : F + : never + : ""; + /** * Conditionally join classNames into a single string * @param {...String} args The expressions to evaluate * @returns {String} The joined classNames */ -function cx(...args: ClassName[]): string; +function cx( + ...args: T +): JoinStrings>; function cx(): string { let str = "", i = 0,