網站搜尋

二進位字串的 Typescript 類型


我想定義一種類型,要求每個字符都是 '1' 或 '0'

type Binary = '1'|'0'

這可以工作,但僅適用於字串長度為 1。有沒有辦法將類型定義為 1 或 0 重複?

也很好奇是否有辦法強制長度?這是我唯一能想到的方法

type BinaryInput = `${Binary}${Binary}${Binary}${Binary}${Binary}`;

答案#1

如果你只想在 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 => "$"

答案#2

品牌類型可能是你最好的選擇。


假設你將二進位數據像數字一樣存儲,例如

const myBinary = 0b1000;
typeof myBinary // 'number'

你可以為原始的 number 類型加上品牌標記:

type Binary = number & { readonly __brand: unique symbol };

對於特定長度:

type Binary<Length extends number> = number & { readonly __brand: unique symbol, length: Length }