type Split = S extends '' ? [] : S extends `${infer T}${D}${infer U}` ? [T, ...Split] : [S]; type UnwrapNumbers = T extends number | number[] ? T : T extends string ? T extends `${infer N extends number}` ? N : never : T extends [infer H extends string, ...infer T extends string[]] ? UnwrapNumbers extends never ? never : [UnwrapNumbers, ...UnwrapNumbers] : []; type IPv4Octets = [number, number, number, number]; type IPv6Octets = string[]; type IPv4 = Split extends [ infer IP extends string, infer SUBNET extends string, ] ? UnwrapNumbers> extends infer OCTETS ? OCTETS extends never ? never : OCTETS extends IPv4Octets ? UnwrapNumbers extends never ? never : CIDR : never : never : never; type IPv6 = Split extends [ infer IP extends string, infer SUBNET extends string, ] ? Split extends IPv6Octets ? UnwrapNumbers extends never ? never : CIDR : never : never; type Test_1 = IPv4<'0.0.0.0/0'>; type Test_2 = IPv4<'255.255.255.255/32'>; type Test_3 = IPv4<'127.0.0.0.1/32'>; type Test_4 = IPv4<'a'>; type Test_5 = IPv4<'1.1.1.a/32'>; type Test_6 = IPv4<'1.1.1.1'>; type Test_7 = IPv4<'1.1.1.1/'>; type Test_8 = IPv4<'1.1.1.1/a'>; type Test_9 = IPv6<'::1/0'>; type Test_10 = IPv6<'ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff/128'>; type Test_11 = IPv6<'::1/128'>; type Test_12 = IPv6<'a'>; type Test_13 = IPv6<'1:1:1:1:1:1:1:1/128'>; type Test_14 = IPv6<'1:1:1:1:1:1:1:1'>; type Test_15 = IPv6<'1:1:1:1:1:1:1:1/'>; type Test_16 = IPv6<'1:1:1:1:1:1:1:1/a'>; // TODO: fully-typed ipv6 (unwrap hex, full and abbreviated address representations)