Skip to content

Strict types for templates #3

@Atulin

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]");

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