Is it possible to define a type that may have every string-value assigned except a few specified ones? I would like to express something along the lines of this (non-compiling) example:
type ReservedNames = "this" | "that"
type FooName = string - ReservedNames;
const f1 : FooName = "This" // Works
const f2 : FooName = "this" // Should error
This isn't currently possible in TypeScript, however you can create a generic type that can handle many of the practical use cases if you add the concrete string value as a parameter of FooName
.
type ReservedNames = "this" | "that"
type NotA<T> = T extends ReservedNames ? never : T
type NotB<T> = ReservedNames extends T ? never : T
type FooName<T> = NotA<T> & NotB<T>
const f1: FooName<'This'> = 'This' // works
const f2: FooName<'this'> = 'this' // error
const f3: FooName<string> = 'this' //error
const f4: FooName<any> = 'this' // error
const f5: FooName<unknown> = 'this' // error
And in a function it works as expected if you make the function generic on the string value:
function foo<T extends string> (v: FooName<T>) {
...
}
foo('this') // error
foo('This') // works