二进制字符串的 Typescript 类型

sta*_*eth 5 typescript

我想定义一个强制每个字符为“1”|“0”的类型

type Binary = '1'|'0'
Run Code Online (Sandbox Code Playgroud)

这可行,但仅适用于字符串长度为 1 的情况。有什么方法可以将类型定义为 1 或 0 重复吗?

还好奇是否有办法强制长度?这是我唯一能想到的

type BinaryInput = `${Binary}${Binary}${Binary}${Binary}${Binary}`;
Run Code Online (Sandbox Code Playgroud)

jse*_*ksn 2

如果您只想在 API 接口上实现类型安全,您可以使用扩展字符串的类型,并且在没有断言的情况下无法获得该类型(我不知道这叫什么,但我喜欢“雪花类型”这个名字)。然后使用类型保护来验证字符串(或者如果您确定并且需要跳过运行时检查来提高性能,则只需断言类型)。

TS 游乐场链接

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 => "$"
Run Code Online (Sandbox Code Playgroud)