// When `T` is neither `any` nor `never` (like `string`) => Returns `IfNot` branchtype A = IfNotAnyOrNever<string, {ifNot: 'VALID'; ifAny: 'IS_ANY'; ifNever: 'IS_NEVER'}>;//=> 'VALID'// When `T` is `any` => Returns `IfAny` branchtype B = IfNotAnyOrNever<any, {ifNot: 'VALID'; ifAny: 'IS_ANY'; ifNever: 'IS_NEVER'}>;//=> 'IS_ANY'// When `T` is `never` => Returns `IfNever` branchtype C = IfNotAnyOrNever<never, {ifNot: 'VALID'; ifAny: 'IS_ANY'; ifNever: 'IS_NEVER'}>;//=> 'IS_NEVER'Note: Wrapping a tail-recursive type with IfNotAnyOrNever makes the implementation non-tail-recursive. To fix this, move the recursion into a helper type. Refer to the following example:
import type {StringRepeat} from 'type-fest';type NineHundredNinetyNineSpaces = StringRepeat<' ', 999>;// The following implementation is not tail recursivetype TrimLeft<S extends string> = IfNotAnyOrNever<S, {ifNot: S extends ` ${infer R}` ? TrimLeft<R> : S}>;// Hence, instantiations with long strings will fail// @ts-expect-errortype T1 = TrimLeft<NineHundredNinetyNineSpaces>;// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// Error: Type instantiation is excessively deep and possibly infinite.// To fix this, move the recursion into a helper typetype TrimLeftOptimised<S extends string> = IfNotAnyOrNever<S, {ifNot: _TrimLeftOptimised<S>}>;type _TrimLeftOptimised<S extends string> = S extends ` ${infer R}` ? _TrimLeftOptimised<R> : S;type T2 = TrimLeftOptimised<NineHundredNinetyNineSpaces>;//=> ''