Last active
May 10, 2022 20:36
-
-
Save jfet97/b36333f089dba6cce01d54b6de196236 to your computer and use it in GitHub Desktop.
types for string long exact/at least/at most n chars
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
type Equal<X, Y> = (<T>() => T extends X ? 1 : 2) extends <T>() => T extends Y | |
? 1 | |
: 2 | |
? true | |
: false; | |
interface StringCostrainType { | |
readonly _N: number; | |
readonly _E: unknown; | |
readonly _type: "exact" | "atleast" | "atmost"; | |
} | |
export interface Exact<N extends number, E = never> extends StringCostrainType { | |
readonly _N: N; | |
readonly _E: E; | |
readonly _type: "exact"; | |
} | |
export interface AtLeast<N extends number, E = never> | |
extends StringCostrainType { | |
readonly _N: N; | |
readonly _E: E; | |
readonly _type: "atleast"; | |
} | |
export interface AtMost<N extends number, E = never> | |
extends StringCostrainType { | |
readonly _N: N; | |
readonly _E: E; | |
readonly _type: "atmost"; | |
} | |
type SameLenTuple<N extends number, _R extends any[] = []> = Equal< | |
N, | |
_R["length"] | |
> extends true | |
? _R | |
: SameLenTuple<N, [0, ..._R]>; | |
// false if same length or shorter | |
type IsLonger<F extends any[], S extends any[]> = F extends [ | |
infer FHEAD, | |
...infer FREST | |
] | |
? S extends [infer SHEAD, ...infer SREST] | |
? IsLonger<FREST, SREST> | |
: true | |
: false; | |
type ExactChecker< | |
SCT extends Exact<number, any>, | |
S extends string, | |
_R extends any[] = [], | |
_S = S | |
> = S extends `${infer C}${infer REST}` | |
? ExactChecker<SCT, REST, [..._R, C], _S> | |
: Equal<SCT["_N"], _R["length"]> extends true | |
? _S | |
: SCT["_E"]; | |
type AtLeastChecker< | |
SCT extends AtLeast<number, any>, | |
S extends string, | |
_R extends any[] = [], | |
_S = S | |
> = S extends `${infer C}${infer REST}` | |
? AtLeastChecker<SCT, REST, [..._R, C], _S> | |
: IsLonger<SameLenTuple<SCT["_N"]>, _R> extends true | |
? SCT["_E"] | |
: _S; | |
type AtMostChecker< | |
SCT extends AtMost<number, any>, | |
S extends string, | |
_R extends any[] = [], | |
_S = S | |
> = S extends `${infer C}${infer REST}` | |
? AtMostChecker<SCT, REST, [..._R, C], _S> | |
: Equal<SCT["_N"], _R["length"]> extends true | |
? _S | |
: IsLonger<SameLenTuple<SCT["_N"]>, _R> extends true | |
? _S | |
: SCT["_E"]; | |
export type Checker< | |
SCT extends StringCostrainType, | |
S extends string | |
> = SCT extends Exact<number, any> | |
? ExactChecker<SCT, S> | |
: SCT extends AtLeast<number, any> | |
? AtLeastChecker<SCT, S> | |
: SCT extends AtMost<number, any> | |
? AtMostChecker<SCT, S> | |
: never; | |
type test_exact_1 = Checker<Exact<3>, "cio">; | |
type test_exact_2 = Checker<Exact<3>, "ci">; | |
type test_exact_3 = Checker<Exact<3>, "ciao">; | |
type test_atleast_1 = Checker<AtLeast<3>, "cio">; | |
type test_atleast_2 = Checker<AtLeast<3, "at least 3 chars plz">, "ci">; | |
type test_atleast_2bis = Checker<AtLeast<3, "at least 3 chars plz">, string>; | |
type test_atleast_3 = Checker<AtLeast<3>, "ciao">; | |
type test_atmost_1 = Checker<AtMost<3>, "cio">; | |
type test_atmost_2 = Checker<AtMost<3>, "ci">; | |
type test_atmost_3 = Checker<AtMost<3>, "ciao">; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment