根据 TypeScript 类型定义,
ProgressEvent.target.result
的类型可以是 string
、ArrayBuffer
或 null
。
我需要开发将文件编码为 Base64 的函数是string
。
但是当它是 null
或 ArrayBuffer
的实例时我必须做什么?
async function encodeFileToBase64(targetFile: File): Promise<string> {
const fileReader: FileReader = new FileReader();
fileReader.readAsDataURL(targetFile);
return new Promise<string>((resolve: (encodedFile: string) => void, reject: (error: Error) => void): void => {
fileReader.onload = (filedHasBeenReadEvent: ProgressEvent<FileReader>): void => {
const fileReadingResult: string | ArrayBuffer | null | undefined = filedHasBeenReadEvent.target?.result;
if (isEitherUndefinedOrNull(fileReadingResult)) {
reject(new Error("Failed to encode the file."));
return;
}
resolve(
fileReadingResult instanceof ArrayBuffer ?
String.fromCharCode.apply(null, new Uint8Array(fileReadingResult)) :
fileReadingResult
);
};
});
}
“文件编码失败。”错误没有足够的详细信息。
null
是什么意思?string
?关于
ArrayBuffer
的相同子问题。
另外,我有 TypeScript 错误
String.fromCharCode.apply(null, new Uint8Array(fileReadingResult))
S2345:Uint8Array 类型的参数不可分配给 number[] 类型的参数 类型 Uint8Array 缺少 number[] 类型的以下属性:pop、push、concat、shift 以及其他 5 个属性。
您不需要使用
event.target
,因为event.target
是“对事件被分派到的对象的引用”,所以它只是fileReader
本身
fileReader.result
的类型取决于您对其调用的操作。根据操作的不同,FileReader 可以是以下之一:
// this errors if actually using this no idea why
interface FileReader {
readAsArrayBuffer(blob: Blob): asserts this is ({ result: ArrayBuffer } | { error: DOMException });
readAsBinaryString(blob: Blob): asserts this is ({ result: string } | { error: DOMException });
readAsDataURL(blob: Blob): asserts this is ({ result: dataUrl } | { error: DOMException });
readAsText(blob: Blob): asserts this is ({ result: string } | { error: DOMException });
}
load
事件,因此 if 意味着 fileReader.error
有错误值。我个人会推荐整个 FileReader 的包装器,例如 https://www.npmjs.com/package/@tanker/file-reader 或 MDN 示例的类型变体:
https://developer.mozilla.org/en-US/docs/Web/API/Event/target#example
const reader = (file: File) =>
new Promise<dataUrl>((resolve, reject) => {
const fr = new FileReader();
fr.onload = () => resolve(fr.result as dataUrl);
fr.onerror = (err) => reject(err);
fr.readAsDataURL(file);
});
type dataUrl = string & { _?: 'dataUrl' } // branded for clearness