在 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/**/*"
]
}
我已经在打字稿中定义了这些接口:
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/**/*" ] }