Search code examples
typescriptstring-literals

Is it possible to create a type in typescript that represents all strings except for a set of string literals?


I would like to use typescript overloading to provide intellisense for a function I'm writing. The signatures only differ by parameter type. The problem I'm having is that if someone passes in something that matches param1 in the first overload, but a param2 that doesn't, then it will fall through to the generic overload. I would like that to not be accepted and have intellisense mark it as an error.

I've tried using conditional typing using Exclude<> which didn't work.

type Exclusion = "Invalid";
type ExcludeString = Exclude<string, Exclusion>;

func(param1: "Activate", param2: (value: SomeInterface) => any): void;
func(param1: ExcludeString, param2: (value: any) => any): void;

When I call func("Activate", (value: NotSomeInterface) => console.log("Invalid")); I would like intellisense to tell the user there's an error. Instead, nothing happens due to the fall through.


Solution

  • You can't define the type directly, Exclude<string, Exclusion> will actually just result in string typescript does not really have the concept of a negated type. There is a proposal to allow something similar (Here) but it's not yet part of the language (at the time of writing 3.3 is the latest version).

    All this being said, we can get a similar effect if we are talking about a function parameter that should not be of a specific value. To do this we need a generic type parameter to capture the actual type of the string passed in. Then we can type the parameter as Exclude<T, Exclusion> and this will yield the expected errors:

    type Exclusion = "Invalid";
    type ExcludeString = Exclude<string, Exclusion>;
    
    function func<T extends string>(param1: Exclude<T, Exclusion>): void {
    
    } 
    
    func("SS")
    func("Invalid") // error