Type for “every possible string value except …”

There isn’t a general solution to this problem since there is no way to express in the typescript type system the fact that a string can be any value except a list. (One might think the conditional type Exclude<string, ReservedNames> would work but it does not, it just evaluates back to string).

As a work around, if we have a function and we specifically want to not allow certain constants to be passed in we can us a conditional type to check for ReservedNames and, if the passed in parameter is ReservedNames then type the input parameter in such a way it is effectively impossible to satisfy (using an intersection type).

type ReservedNames = "this" | "that"
type FooName = Exclude<string, ReservedNames>;
const f1 : FooName = "This" // Works
const f2 : FooName = "this" // One might expect this to work but IT DOES NOT as FooName is just evaluates to string


function withName<T extends string>(v: T & (T extends ReservedNames ? "Value is reserved!": {})) {
  return v;
}

withName("this"); // Type '"this"' is not assignable to type '"Value is reserved!"'.
withName("This") // ok

Playground

Leave a Comment