Mykyta Smirnov
Mykyta Smirnov

Reputation: 79

Typescript: Allow generic type but not it's subtype

F.e. I want to allow any object but not exact instance of some subtype The code below doesn't give me any warns and successfully compiles.

type Non<N, T> = T extends N ? never : T;

const a: Non<Error, object> = new Error(); // Should get type error

Upvotes: 0

Views: 1089

Answers (1)

Linda Paiste
Linda Paiste

Reputation: 42188

Your type does work, just not in the way that you're using it.

When you use the type hint const a: Non<Error, object>, the type only gets evaluated once and it's evaluated with the specific values that you provided it: N = Error and T = object.

type Non<Error, object> 
   = object extends Error ? never : object
   = false ? never : object
   = object

In other words, Non<Error, object> just equals object. Always. That's because there are no variables here, we are just comparing the type object and the type Error.

Here's an example of a usage where your Non type makes sense, using it as the assertion on a type guard function.

const isNotError = <T>(value: T): value is Non<Error, T> => {
    return ! (value instanceof Error)
}

const checkVal = (value: Error | {s: string} ): string => {
    if ( isNotError( value ) ) {
        // value cannot be of type Error
        return value.s;
    } else {
        // value must be of type Error
        return value.message;
    }
}

FYI what you are writing here is already a built-in type called Exclude. Exclude puts the arguments in the opposite order of your Non type, so thing that you are excluding goes second.

Upvotes: 2

Related Questions