Home > OS >  Typescript template literals type force structure
Typescript template literals type force structure

Time:05-11

I have the following code:

type Foo<T extends string = string> = `bar-${T}-foo`;

const v: Foo = 'bar-g-foo'

That works as expected, but it doesn't force the structure. The following is also valid:

  const v: Foo = 'bar--foo'

How can I force the usage of T?

CodePudding user response:

It might not be the best approach, becasue of the reliance on the function assigning the value of generic type dynamically, but depending on your usage this could also be vallid

type NonEmptyString<T extends string> = T extends "" ? never : T;

function fn<T extends string>(a: `bar-${NonEmptyString<T>}-foo`) {
    // ...
}

fn("bar--foo"); // Error
fn("bar-g-foo"); // No error
fn("bar-gg-foo"); // No error

Playground link

CodePudding user response:

The problem here is to check for an empty string. Read more about this problem here: How to write a string type that does not contain an empty string in TypeScript

Based on the stack from above you could do something like this:

type Character = 'a' | 'b' | 'c' | ... ; // Here all possible 1 letter strings
type NonEmptyString = `${Character}${string}`;
type Foo<T extends string = NonEmptyString> = `bar-${T}-foo`;

const v: Foo = 'bar-a-foo' // ✔
const x: Foo = 'bar--foo' // ❌ Type '"bar--foo"' is not assignable to type

Playground link

  • Related