keepass - 如何在 TypeScript 5.7 中将 “Buffer” 转换为 “ArrayBuffer”?
根据 TypeScript 5.7 的公告,我现在受到了 ES2024 对缓冲区(Buffers)的更改的影响。尤其是缓冲区泛型(Buffer Generics)的这一更改。
我正在使用一个 KeePass 文件。为此,我通过 npm 包 "kdbxweb" "^2.1.1" 加载并打开该文件。
环境:"typescript": "^5.7.3","@types/node": "^22.10.5"。(即当前最新版本)
import fs from 'fs';
import path from 'path';
import * as kdbxweb from 'kdbxweb';
async getClientSecret(): Promise<string> {
const fileBuffer: Buffer<ArrayBufferLike> = fs.readFileSync(KeePassFilePath);
const keePassFileBuffer: ArrayBufferLike = fileBuffer.buffer;
const keePassDB: kdbxweb.Kdbx = await kdbxweb.Kdbx.load(keePassFileBuffer, new kdbxweb.Credentials(kdbxweb.ProtectedValue.fromString(myPW)));
// ...
}
在升级到“ES2024”(通过“ESNext”)后,npx tsc 报错:
error TS2345: Argument of type 'ArrayBufferLike' is not assignable to parameter of type 'ArrayBuffer'.
Type 'SharedArrayBuffer' is missing the following properties from type 'ArrayBuffer': resizable, resize, detached, transfer, transferToFixedLength
我不知道如何解决这个问题。库的 load 函数声明为:
static load(data: ArrayBuffer, credentials: KdbxCredentials, options?: {
preserveXml?: boolean;
}): Promise<Kdbx>;
当 fs.readFileSync() 返回一个 Buffer<ArrayBufferLike>(来自 "@types/node": "^22.10.5"),这会使 buffer 属性返回一个 ArrayBufferLike。
我如何才能将它们合并在一起(不期望出现 TS 错误或将其转换为 unknown 等)?也就是说,如何将 Buffer<ArrayBufferLike> 正确地转换为 ArrayBuffer?
盲目转换为
const fileBuffer = fs.readFileSync(KeePassFilePath) as Buffer<ArrayBuffer>;
确实可以消除错误,但我怎么知道正确的实际类型呢?想象其他供应商,他们并没有提供某种保证说这是一个真正的 ArrayBuffer。所以这对我来说不是一个可行的解决方案。
答案#1
在你的代码中,你直接使用了 KeePassFileBuffer.buffer,这可能会导致内容不匹配的潜在问题,因为这是内部的 ArrayBuffer,可能包含额外的数据。按照你使用的方式,这种情况不太可能发生,但最好确保提取相关部分。
这就是你如何将 Buffer<ArrayBufferLike> 转换为 ArrayBuffer:
import fs from 'fs/promises';
import path from 'path';
import * as kdbxweb from 'kdbxweb';
import {ProtectedValue} from "kdbxweb";
// Convert Node.js Buffer to ArrayBuffer
function bufferToArrayBuffer(buffer: Buffer): ArrayBuffer {
return buffer.buffer.slice(buffer.byteOffset, buffer.byteOffset + buffer.byteLength) as ArrayBuffer;
}
// And apply that to your code
class SomeClass {
private keepassPassword: ProtectedValue = ProtectedValue.fromString('123');
async getClientSecret(): Promise<string> {
const KeePassFileBuffer = await fs.readFile(path.resolve('user.kdbx'));
const keePassDB: kdbxweb.Kdbx = await kdbxweb.Kdbx.load(bufferToArrayBuffer(KeePassFileBuffer), new kdbxweb.Credentials(this.keepassPassword));
// ....
return '?';
}
}
这不直接与你的问题相关,但请注意我切换到了异步的 Node.js API fs/promises,它更好地支持 promises。
答案#2
以下方法似乎可行并能满足类型检查器,但它可能不是最有效的方式,因为它涉及创建几个 Uint8Arrays。
const fileBuffer: ArrayBufferLike = new SharedArrayBuffer(16);
const ui8Array: Uint8Array<ArrayBufferLike> = new Uint8Array(fileBuffer);
const actualArrayBuffer: ArrayBuffer = new ArrayBuffer(ui8Array.length);
const actualArrayBufferView: Uint8Array<ArrayBuffer> = new Uint8Array(actualArrayBuffer);
actualArrayBufferView.set(ui8Array);
// actualArrayBuffer now holds the contents of fileBuffer, but is of type ArrayBuffer
