在 TypeScript 中区分 Node.js 缓冲区的切片类型

Discriminate type of slice of Node.js Buffer in TypeScript

我已经在打字稿中定义了这些接口:

enum TypeId {
  A = 0
  B = 1
  C = 2
}

interface A {
  id: TypeId.A
}

interface B {
  id: TypeId.B
  foo: string
}

interface C {
  id: TypeId.C
}

type MyType = A | B | C

现在我想从 Buffer 实例中反序列化这些类型。我读取一个字节来获取 ID,如果它匹配 TypeId.B,则必须读取 4 个字节以获得 foo 的值。

如何在签名为 parse(buffer: Buffer): MyType 的函数中执行此操作?

感谢您的帮助。

我推断你所指的Buffer就是来自Node.js的那个。

这是您在 Node 中解析二进制数据的方式:(具体来说,在您的情况下)一个整数,可选地后跟一个 UTF-8 字符串:

./src/index.ts:

import {TextDecoder, TextEncoder} from 'util';

enum Id {
  A = 0,
  B = 1,
  C = 2,
}

interface A {
  id: Id.A;
}

interface B {
  id: Id.B;
  foo: string
}

interface C {
  id: Id.C;
}

type MyType = A | B | C;

export function parse (buf: Buffer): MyType {
  const id = buf.readUInt8(0);
  if (![Id.A, Id.B, Id.C].includes(id)) throw new Error('Invalid ID');
  if (id === Id.B) {
    // equivalent:
    // const foo = buf.slice(1, 5).toString('utf-8');
    const foo = new TextDecoder().decode(buf.slice(1, 5));
    return {id, foo};
  }
  return {id};
}

function main () {
  // equivalent:
  // const buf0 = Buffer.from([0, ...Buffer.from('hello', 'utf-8')]);
  const encoder = new TextEncoder();
  const buf0 = Buffer.from([0, ...encoder.encode('hello')]);
  const buf1 = Buffer.from([1, ...encoder.encode('example string')]);
  const buf2 = Buffer.from([2, ...encoder.encode('another one')]);

  console.log(parse(buf0)); // { id: 0 }
  console.log(parse(buf1)); // { id: 1, foo: 'exam' }
  console.log(parse(buf2)); // { id: 2 }
}

main();

For reference, this is the TSConfig I used:

{
  "compilerOptions": {
    "exactOptionalPropertyTypes": true,
    "isolatedModules": true,
    "lib": [
      "ESNext"
    ],
    "module": "ESNext",
    "moduleResolution": "Node",
    "noUncheckedIndexedAccess": true,
    "outDir": "dist",
    "strict": true,
    "target": "ESNext",
  },
  "include": [
    "./src/**/*"
  ]
}