typescripttypestemplate-literalstypescript-template-literals

How can I define a `BinaryString` type in TypeScript?


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?


Solution

  • 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:

    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