Offroaders123 / NBTify

A library to read and write NBT files on the web!
http://npm.im/nbtify
MIT License
42 stars 5 forks source link

Primitive Type Shape Checking #13

Closed Offroaders123 closed 1 year ago

Offroaders123 commented 2 years ago

Relating to #6, my custom primitive type classes aren't typed with enough strength to differentiate each other, in TypeScript's terms. Since the shape of each class is the same, even if you declare the type of x as one of the primitive number types, it will still allow the value to be a different type. A better example, using code:

import { Byte, Short, Int, Float } from "nbtify";

interface LevelDat {
  Key: Byte
}

const data: LevelDat = {
  Key: 5 // Should be `new Byte(5)`, however it doesn't throw an error for this, while it should. It appears to be because the value has the same shape as the Byte object, nothing is unique between the two.
};
Offroaders123 commented 1 year ago

Solved! Looking into the type definitions for the TypedArray instances (since they also share the same thing of having identical types), they differentiate between each other with the get [Symbol.toStringTag]() declaration. You can assert with with an as const string value, and that will be enough for TS to tell them apart. Perfect! You also get [object ThingName] coalescing support with that too, which is nice. Another alternative that works, but I didn't go with, you can declare either a TS-only private propName on the class, or a JS-supported #privateField too. Both of those will be noted in the resulting types too, and show that the two classes can't be matched.