Is there a way to make a specific type that matches anything except for arrays, for use with extends as a constraint on a generic value?
Things that don't work:
type NotArrayExplicit = Exclude<any, any[]>;
const shouldFail: NotArrayExplicit = [1,2,3];
// ^ Permitted by typechecker (opposite of desired behavior)
// This works for generics, yet can't be used with <T extends NotArrayGeneric>
type NotArrayGeneric<T> = T & Exclude<T, Array<any>>;
const rejectSuccess: NotArrayGeneric<number[]> = [1,2,3,4];
// ^ Error: Type 'number' is not assignable to type 'never'.
function thisDoesntWork<T extends NotArrayGeneric<T>>(nonArray: T): T {return nonArray;}
// ^ Error: Type parameter 'T' has a circular constraint
The goal type is something that can be used as a constraint on a generic type, like <T extends NonArray>, in a clean and idiomatic way.