我想为我的TypeScrip类实现[Symbol.iterator]
,它允许我进行强类型的元组解构.
例如,这个类在内部存储了一个强类型的元组,我通过直接访问成员成功地对其进行了分解:
class Deserializer<ParsedArgs extends Array<unknown> = []> {
deserialized: ParsedArgs;
// ...
}
const [str, vec] = (new Deserialized(/* ... */)).deserialized
我想添加一个[Symbol.iterator]
实现,这样我就可以go 掉.deserialized
.我实际上可能不会这样做,因为这是一个相当出人意料的API,但在TypeScrip中这可能吗?
我试过了,但各个组件最终都输入了string | Vector3
,原因很明显:
[Symbol.iterator](): Iterator<ParsedArgs[number]> {
let index = 0;
const data = this.deserialized;
return {
next: function () {
return { value: data[++index], done: !(index in data) }
}
};
}
Typescript playground link for below full test code个
type Vector3 = [x: number, y: number, z: number];
type DeserializeResult<T> = [deserialized: T, newOffset: number];
// Deserialize a length-prefixed string
function deserializeString(
args: ArrayBuffer,
offset: number
): DeserializeResult<string> {
const len = new Uint32Array(args.slice(offset, offset + 4))[0];
const str = new TextDecoder().decode(
args.slice(offset + 4, offset + 4 + len)
);
return [str, offset + 4 + len];
}
// Deserialize three floats in a row
function deserializeVector3(
args: ArrayBuffer,
offset: number
): DeserializeResult<Vector3> {
const floatArr = new Float32Array(args.slice(offset, offset + 3 * 4));
const result: Vector3 = [floatArr[0], floatArr[1], floatArr[2]];
return [result, offset + 3 * 4];
}
class Deserializer<ParsedArgs extends Array<unknown> = []> {
buffer: ArrayBuffer;
offset: number;
deserialized: ParsedArgs;
constructor(buffer: ArrayBuffer, deserialized: ParsedArgs, offset: number) {
this.deserialized = deserialized;
this.buffer = buffer;
this.offset = offset;
}
private peel<T>(
deserializerFunc: (
buffer: ArrayBuffer,
offset: number
) => DeserializeResult<T>
) {
const [value, offset] = deserializerFunc(this.buffer, this.offset);
this.offset = offset;
this.deserialized.push(value);
return this as unknown as Deserializer<[...ParsedArgs, T]>;
}
Vector3() {
return this.peel(deserializeVector3);
}
string() {
return this.peel(deserializeString);
}
}
function deserialize(buffer: ArrayBuffer): Deserializer<[]> {
return new Deserializer(buffer, [], 0);
}
async function test() {
const buffer = await (new Blob([
// str1
new Uint32Array([3]),
"abc",
// vec1
new Float32Array([123.456, 7, 8]),
// str2
new Uint32Array([5]),
"hello",
// vec2
new Float32Array([-1, -2, -3]),
]).arrayBuffer())
const [str1, vec1, str2, vec2] = deserialize(buffer)
.string()
.Vector3()
.string()
.Vector3().deserialized;
// assertions
function check<T extends string | Vector3>(t: T) {
console.log(t)
}
check<string>(str1)
check<Vector3>(vec1)
check<string>(str2)
check<Vector3>(vec2)
}
test()