I would like to define a type that enforces each character be '1'|'0'
type Binary = '1'|'0'
this works, but only with a string length of 1. Is there any way to define the type as 1 or 0 repeating?
Also curious if there is a way to enforce length? This is the only thing I could come up with
type BinaryInput = `${Binary}${Binary}${Binary}${Binary}${Binary}`;
CodePudding user response:
If you just want type safety at the interfaces of your API, you can use a type that extends string and is impossible to obtain without assertion (I don't know what this is called, but I like the name "snowflake type"). Then use a type guard to validate the strings (or simply assert the type if you're sure and need the performance gain of skipping the runtime check).
type Binary<N extends number = number> = string & {
readonly BinaryStringLength: unique symbol;
length: N;
};
class AssertionError extends Error {
name = 'AssertionError';
}
function assertIsBinaryString <L extends number>(
str: string,
length?: L,
): asserts str is Binary<L> {
if (typeof length === 'number' && str.length !== length) {
throw new AssertionError('Binary string has invalid length');
}
for (const unit of str) {
if (unit !== '0' && unit !== '1') {
throw new AssertionError('Invalid character in binary string');
}
}
}
// Use:
function asDecimal (bStr: Binary): number {
return parseInt(bStr, 2);
}
function byteAsChar (byte: Binary<8>): string {
return new TextDecoder().decode(new Uint8Array([asDecimal(byte)]));
}
let str = '00100100';
// console.log(asDecimal(str)); // string not assignable to Binary
/* ^^^
Error 2345 */
assertIsBinaryString(str);
console.log(asDecimal(str)); // ok now => 36
// console.log(byteAsChar(str)); // Binary<number> not assignable to Binary<8> because number not assignable to 8
/* ^^^
Error 2345 */
assertIsBinaryString(str, 8);
console.log(byteAsChar(str)); // ok now => "$"
CodePudding user response:
This answer was given for enforcing Hex strings: https://stackoverflow.com/a/56720473/11838606
See if you can adapt it for Binary strings.