参数类型字符串 | ArrayBuffer 不可分配给参数类型字符串
Argument type string | ArrayBuffer is not assignable to parameter type string
第 15 行出现 TS 错误,尤其是 e.target.result
。
Argument type string | ArrayBuffer is not assignable to parameter type string Type ArrayBuffer is not assignable to type string
let fileTag = document.getElementById("filetag"),
preview = document.getElementById("preview");
fileTag.addEventListener("change", function() {
changeImage(this);
});
function changeImage(input) {
let reader;
if (input.files && input.files[0]) {
reader = new FileReader();
reader.onload = function(e) {
preview.setAttribute('src', e.target.result);
}
reader.readAsDataURL(input.files[0]);
}
}
已添加HTML
<div class="img-container">
<input type="file" id="filetag">
<img src="" class="profImage" id="preview" alt="profilePic">
</div>
你或许可以做到:
function ab2str(buf: ArrayBuffer): string {
return String.fromCharCode.apply(null, new Uint16Array(buf));
}
// ...
reader.readAsDataURL(typeof input.files[0] === 'string' ? input.files[0] : ab2str(input.files[0]))
或者,如果您是肯定的,它将始终是一个字符串:
reader.readAsDataURL(input.files[0] as string);
基本上如果是字符串就直接用,但是如果是ArrayBuffer,先转成字符串。不确定打字稿是否能够遵循这一点。
https://developers.google.com/web/updates/2012/06/How-to-convert-ArrayBuffer-to-and-from-String
否则,只需执行:
preview.setAttribute('src', e.target.result as string);
同样,假设你是肯定的,它实际上总是一个字符串
(独立于实际答案,考虑使用 URL.createObjectURL
而不是将 File
转换为 data:
URI;它将为您节省一些虚假字符串转换的资源。)
问题是类型检查在本地工作。
let preview = document.getElementById("preview");
let reader = new FileReader();
reader.onload = function(e) {
preview.setAttribute('src', e.target.result);
}
根据周围的上下文,TypeScript 知道 preview
是一个 DOM 节点,因此 preview.setAttribute
需要两个字符串参数。它还知道 e.target
是一个 FileReader
, and therefore its property result
可以是一个字符串或一个 ArrayBuffer
。具体是哪一个取决于之前在 FileReader
上调用的方法,但此信息很难在类型系统中表达,并且无论如何在事件处理程序中都不可用。所有类型检查器都知道,事件处理程序可能在 readAsArrayBuffer
被调用后调用,很远很远的地方在同一个 FileReader
对象上。
因为在这种情况下你比类型检查器更清楚,你可以使用 type assertion 来说服它该值确实是一个字符串:
reader.onload = function(e) {
preview.setAttribute('src', e.target.result as string);
}
如果您不想在代码中到处乱扔类型断言,请考虑将您的代码包装在更易于类型检查的抽象中,例如:
function readFileAsDataURL(file): Promise<string> {
return new Promise((accept, reject) => {
const reader = new FileReader();
reader.onload = function (ev) {
accept(ev.target.result as string);
};
/* XXX: rejecting with an event is rather unorthodox */
reader.onabort = reader.onerror = function (ev) {
reject(ev);
}
reader.readAsDataURL(file);
});
}
async function changeImage(input) {
preview.setAttribute('src', await readFileAsDataURL(input.files[0]));
}
现在,如果您记得在代码中到处使用 readFileAsDataURL
而不是直接构造 FileReader
,那么唯一需要类型断言的地方就是在该函数内部。
第 15 行出现 TS 错误,尤其是 e.target.result
。
Argument type string | ArrayBuffer is not assignable to parameter type string Type ArrayBuffer is not assignable to type string
let fileTag = document.getElementById("filetag"),
preview = document.getElementById("preview");
fileTag.addEventListener("change", function() {
changeImage(this);
});
function changeImage(input) {
let reader;
if (input.files && input.files[0]) {
reader = new FileReader();
reader.onload = function(e) {
preview.setAttribute('src', e.target.result);
}
reader.readAsDataURL(input.files[0]);
}
}
已添加HTML
<div class="img-container">
<input type="file" id="filetag">
<img src="" class="profImage" id="preview" alt="profilePic">
</div>
你或许可以做到:
function ab2str(buf: ArrayBuffer): string {
return String.fromCharCode.apply(null, new Uint16Array(buf));
}
// ...
reader.readAsDataURL(typeof input.files[0] === 'string' ? input.files[0] : ab2str(input.files[0]))
或者,如果您是肯定的,它将始终是一个字符串:
reader.readAsDataURL(input.files[0] as string);
基本上如果是字符串就直接用,但是如果是ArrayBuffer,先转成字符串。不确定打字稿是否能够遵循这一点。
https://developers.google.com/web/updates/2012/06/How-to-convert-ArrayBuffer-to-and-from-String
否则,只需执行:
preview.setAttribute('src', e.target.result as string);
同样,假设你是肯定的,它实际上总是一个字符串
(独立于实际答案,考虑使用 URL.createObjectURL
而不是将 File
转换为 data:
URI;它将为您节省一些虚假字符串转换的资源。)
问题是类型检查在本地工作。
let preview = document.getElementById("preview");
let reader = new FileReader();
reader.onload = function(e) {
preview.setAttribute('src', e.target.result);
}
根据周围的上下文,TypeScript 知道 preview
是一个 DOM 节点,因此 preview.setAttribute
需要两个字符串参数。它还知道 e.target
是一个 FileReader
, and therefore its property result
可以是一个字符串或一个 ArrayBuffer
。具体是哪一个取决于之前在 FileReader
上调用的方法,但此信息很难在类型系统中表达,并且无论如何在事件处理程序中都不可用。所有类型检查器都知道,事件处理程序可能在 readAsArrayBuffer
被调用后调用,很远很远的地方在同一个 FileReader
对象上。
因为在这种情况下你比类型检查器更清楚,你可以使用 type assertion 来说服它该值确实是一个字符串:
reader.onload = function(e) {
preview.setAttribute('src', e.target.result as string);
}
如果您不想在代码中到处乱扔类型断言,请考虑将您的代码包装在更易于类型检查的抽象中,例如:
function readFileAsDataURL(file): Promise<string> {
return new Promise((accept, reject) => {
const reader = new FileReader();
reader.onload = function (ev) {
accept(ev.target.result as string);
};
/* XXX: rejecting with an event is rather unorthodox */
reader.onabort = reader.onerror = function (ev) {
reject(ev);
}
reader.readAsDataURL(file);
});
}
async function changeImage(input) {
preview.setAttribute('src', await readFileAsDataURL(input.files[0]));
}
现在,如果您记得在代码中到处使用 readFileAsDataURL
而不是直接构造 FileReader
,那么唯一需要类型断言的地方就是在该函数内部。