I'd like to define a type that will only allow nonempty binary strings. Something like:
type BinChar = "0" | "1"
type BinString = `${BinChar}${BinString}`
const b: BinString = "01" // should work
const a: BinString = "ab" // should fail
Unfortunately, this yields a "Type alias BinString circularly references itself" error.
Any other way to solve this?
I'd like to define a type that will only allow nonempty binary strings. Something like:
type BinChar = "0" | "1"
type BinString = `${BinChar}${BinString}`
const b: BinString = "01" // should work
const a: BinString = "ab" // should fail
Unfortunately, this yields a "Type alias BinString circularly references itself" error.
Any other way to solve this?
Share Improve this question asked 2 days ago Jean-Philippe PelletJean-Philippe Pellet 60k22 gold badges176 silver badges239 bronze badges2 Answers
Reset to default 1I think that's impossible since you need to create all possible values with your type which like infinite, neither TS can infer generic types, you could use a factory function:
Playground
type BinString<T extends string, O = T>= T extends `${'0' | '1'}${infer A}` ? A extends '' ? O : BinString<A, O> : never;
function binaryString<T extends string>(arg: BinString<T>): T { return arg }
const bs = binaryString('01101010'); // ok
const bs2 = binaryString('003'); // error
const bs3 = binaryString(''); // error
Further improvements could be using flavored types, though you can reuse the check conditional type for functions' arguments:
Playground
type BinString = string & {_binaryString: true};
type IsBinString<T extends string, O = T>= T extends `${'0' | '1'}${infer A}` ? A extends '' ? O : IsBinString<A, O> : never;
function binaryString<T extends string>(arg: IsBinString<T>): BinString { return arg }
const bs = binaryString('01101010');
declare function binaryStringToNumber(str: BinString): number;
binaryStringToNumber(bs); // ok
binaryStringToNumber('01'); // error
You could try using Regex to 'test' the string, since this falls into that category.
type BinaryString = `${string & { __brand: "{0|1}*" }}`;
function assertBinaryString(value: string): BinaryString {
const binaryRegex = /^[01]*$/;
if (binaryRegex.test(value)) {
return value as BinaryString;
} else {
throw new Error("Invalid binary string format");
}
}
let validDate: BinaryString = assertBinaryString("010101");
console.log(validDate); // Output : 010101
let invalidDate: BinaryString = assertBinaryString("random");
console.log(invalidDate) // Output : Error
Source: How to Define a Regex-Matched String Type in TypeScript ?