Skip to content

Commit

Permalink
Merge pull request #5 from duplojs/feat/3
Browse files Browse the repository at this point in the history
feat(3): add function createInterpolation
  • Loading branch information
mathcovax authored Feb 14, 2025
2 parents 171e105 + 37d8d87 commit be31acc
Show file tree
Hide file tree
Showing 4 changed files with 142 additions and 0 deletions.
1 change: 1 addition & 0 deletions scripts/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ export * from "./getTypedEntries";
export * from "./getTypedKeys";
export * from "./hasKey";
export * from "./incremente";
export * from "./interpolation";
export * from "./isEqual";
export * from "./overrideInterface";
export * from "./partialKeys";
Expand Down
96 changes: 96 additions & 0 deletions scripts/interpolation.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
import { type ExpectType } from "./expectType";
import { createInterpolation, type CreateInterpolationContract } from "./interpolation";

describe("interpolation", () => {
it("simple replace", () => {
const interpolation = createInterpolation("query-{id}");

type check1 = ExpectType<
CreateInterpolationContract<typeof interpolation>,
`query-${string}`,
"strict"
>;

const result = interpolation({
id: "aa",
});

type check = ExpectType<typeof result, "query-aa", "strict">;

expect(result).toBe("query-aa");
});

it("multi replace", () => {
const interpolation = createInterpolation("query-{id}-{test}");

type check1 = ExpectType<
CreateInterpolationContract<typeof interpolation>,
`query-${string}-${string}`,
"strict"
>;

const result = interpolation({
id: "aa",
test: "vol",
});

type check = ExpectType<typeof result, "query-aa-vol", "strict">;

expect(result).toBe("query-aa-vol");
});

it("no interpolation", () => {
const interpolation = createInterpolation("query");

type check1 = ExpectType<
CreateInterpolationContract<typeof interpolation>,
"query",
"strict"
>;

const result = interpolation();

type check = ExpectType<typeof result, "query", "strict">;

expect(result).toBe("query");
});

it("complex interpolation", () => {
const interpolation = createInterpolation("{id1}{id2}{id3}{id4}");

type check1 = ExpectType<
CreateInterpolationContract<typeof interpolation>,
string,
"strict"
>;

const result = interpolation({
id1: "1",
id2: "2",
id3: "3",
id4: "4",
});

type check = ExpectType<typeof result, "1234", "strict">;

expect(result).toBe("1234");
});

it("replace multi", () => {
const interpolation = createInterpolation("{id}{id}");

type check1 = ExpectType<
CreateInterpolationContract<typeof interpolation>,
string,
"strict"
>;

const result = interpolation({
id: "1",
});

type check = ExpectType<typeof result, "11", "strict">;

expect(result).toBe("11");
});
});
44 changes: 44 additions & 0 deletions scripts/interpolation.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { type IsEqual } from "./isEqual";

export type ExtractInterpolationId<
GenericValue extends string,
> = GenericValue extends `${string}{${infer InferedInterpolationId}}${infer InferedEndValue}`
? InferedInterpolationId | ExtractInterpolationId<InferedEndValue>
: never;

export type ReplaceInterpolationIdByValues<
GenericValue extends string,
GenericInterpolationValues extends Record<string, string>,
> = GenericValue extends `${infer InferedStartValue}{${infer InferedInterpolationId}}${infer InferedEndValue}`
? InferedInterpolationId extends keyof GenericInterpolationValues
? `${InferedStartValue}${GenericInterpolationValues[InferedInterpolationId]}${ReplaceInterpolationIdByValues<InferedEndValue, GenericInterpolationValues>}`
: `${InferedStartValue}${string}${ReplaceInterpolationIdByValues<InferedEndValue, GenericInterpolationValues>}`
: GenericValue;

export type CreateInterpolationContract<
GenericInterpolationFunction extends ((value: Record<string, string>) => string),
> = ReplaceInterpolationIdByValues<
ReturnType<GenericInterpolationFunction>,
{}
>;

export function createInterpolation<
GenericValue extends string,
GenericInterpolationId extends ExtractInterpolationId<GenericValue>,
>(value: GenericValue) {
return <
GenericInterpolationMapperValue extends string,
GenericInterpolationValues extends Record<GenericInterpolationId, GenericInterpolationMapperValue>,
>(
...[interpolationValues]: IsEqual<GenericInterpolationId, never> extends true
? []
: [interpolationValues: GenericInterpolationValues]
): ReplaceInterpolationIdByValues<GenericValue, GenericInterpolationValues> => (
interpolationValues
? value.replace(
/\{([^}]*)\}/g,
(match, interpolationId: GenericInterpolationId) => interpolationValues[interpolationId],
)
: value
) as never;
}
1 change: 1 addition & 0 deletions test/integration/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ it("export all", () => {
"InvalidBytesInStringError",
"UnPartialError",
"clone",
"createInterpolation",
"entryUseMapper",
"escapeRegExp",
"getTypedEntries",
Expand Down

0 comments on commit be31acc

Please sign in to comment.