Closed Offroaders123 closed 1 year ago
Now all objects can be accepted into NBTify, build from classes or anything else. The type checking for them currently isn't working still, so you will get a TypeScript error for passing in classes that don't have the CompoundTag
index signature present on them. They will indeed be readable by NBTify though. You can combat this by adding an index signature to your class, but that is not my end-all solution. This will break your type definitions for your class, since it will allow any properties to be assigned to your object, because of the index signature.
I want to have a way to validate incoming objects by using an index signature, but without requiring them to also have the index signature. So, essentially:
export type Tag = string | number | boolean | CompoundTag;
export interface CompoundTag {
// [name: string]: satisfies Tag; <-- This is the ideal way of type-checking the incoming object
[name: string]: Tag;
}
export declare function write(data: CompoundTag): Promise<Uint8Array>;
export class MyNBT {
ExampleKey = 5;
Heya = true;
ValidNBT = "oh yeah!";
}
await write(new MyNBT());
// Argument of type 'MyNBT' is not assignable to parameter of type 'CompoundTag'.
// Index signature for type 'string' is missing in type 'MyNBT'. ts(2345)
Currently, only non-extended
Object
objects are allowed to validate as a Compound tag. I want to allow NBTify users (me included!) to be able to construct their own NBT-serializable objects, by using ES6 classes. This would allow you to create interface types for in-game NBT objects, and also write your own JavaScript/TypeScript class that will generate the exact same structure on the fly, without needing to have the game generate them.At first, I couldn't figure out how I can distinguish serializable vs. non serializable objects, since your own custom classes won't directly have the
Object
prototype as the first parent, so that won't work to check the class type. This would invalidate your custom classes from being able to be read as a valid Compound tag structure. My current code is there for this, because I want to throw error handling messages when you try to serialize non-NBT kinds of objects, likeRegExp
,TextEncoder
, or other ones like that. Essentially, any standard library objects that shouldn't be parseable down to NBT, unless you explicitly wanted to allow one to do that.Similar to how
toJSON
andget [Symbol.toStringTag]
work (Check out the Well-known Symbols section on MDN), I realized a really nice way to add a check for if any given object is NBT-serializable, I could check using both the originalObject
prototype method I am currently using, and with the use of a new property, which would be something along the lines ofget [Symbol("toNBT")]
, or something like that. The new check would first check if the given object is a direct decendent ofObject
(current behavior). And if that's not the case, check if the object has theget [Symbol("toNBT")]
present. If either of those are true, than attempt to parse that object as a Compound tag.I'm not sure exactly what the Symbol will be called yet, and I'm also not sure what I want the return value of the property getter to be, either. I'm wondering if it should work like
toJSON
, in that you can add NBT-serializability (what a mouthful/typeful XD) to non-originally serializable objects.In typing that last sentence, I'm curious if I should remove the forceful error handling, and make it work like how
JSON.stringify()
handles it, in the fact that it coalesces objects without thetoJSON
property as just an empty{ }
object. This will make the writing process less strict, but it does make it more in-line with what the JSON module does, and I'm trying to do that where applicable with NBTify too, since I want it to feel like it's part of the JS standard library.If that last paragraph is what I go with, then I can simply serialize "unsupported" (or rather, unexpected) objects like how the JSON module does it. I would remove the error checking for this, and it would simply be enforced with user-defined
get [Symbol("toNBT")]
properties and TypeScript definitions. That's the middle ground I have been following with the rest of the library too, and it has made making data structures really nice too, since it's just JavaScript objects and primitives that you are working with, rather than NBT-related primitives.