Reputation: 60006
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?
Upvotes: 1
Views: 48
Reputation: 11
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 ?
Upvotes: 0
Reputation: 23602
I 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:
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:
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
Upvotes: 1