Skip to content

Strict types for templates #3

Description

@Atulin

Typescript types are bonkers insane, so we could go as far as validate the templates. For example, showing error on '{DD}-{xx}' saying, that xx is not valid here.

Sample code with (lots of) comments on TS playground

Shortened code without comments:

type Foo = 'a' | 'b' | 'c';

type ReplaceWithFoo<T extends string> = T extends `${infer P}[string]${infer Rest}`
  ? `${P}[${Foo}]${ReplaceWithFoo<Rest>}`
  : T;

type InferTemplateFromActual_Strict<S extends string> =
  S extends ""
    ? ""
    : S extends `${infer P}[${Foo}]${infer Rest}`
      ? InferTemplateFromActual_Strict<Rest> extends infer R
        ? R extends string
          ? `${P}[string]${R}`
          : never
        : never
      : S extends `${string}[${string}]${string}`
        ? never
        : S;

declare function fn<
  S extends string,
  T extends string = InferTemplateFromActual_Strict<S>
>(
  str: S extends ReplaceWithFoo<T> ? S : never
): T;

// Valid calls:
const template1 = fn("path/to/[a]/file");
const template2 = fn("prefix-[b]-middle-[c]");
const template3 = fn("no_placeholders");
const template4 = fn("[a]-[b]");
const template5 = fn("");

// Invalid calls (should now correctly produce type errors):
const invalid1 = fn("path/to/[string]/file");
const invalid2 = fn("path/to/[d]/file");
const invalid3 = fn("prefix-[a]-[d]");

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions