Conversation
| data8 : DataType<number>, | ||
| data16: DataType<number>, | ||
| data24: DataType<number>, | ||
| data32: DataType<number>, | ||
| data40: DataType<number>, | ||
| data48: DataType<number>, | ||
| data56: DataType<number>, |
There was a problem hiding this comment.
- data40/48/56 typed incorrectly as
DataType<number>- should beDataType<Buffer> - data64 missing from type declarations
| single: DataType<number>, | ||
| double: DataType<number>, | ||
|
|
||
| octstr: DataType<string>, |
There was a problem hiding this comment.
octstr typed as DataType<string> - should be DataType<Buffer>
| Array0: <Type>(type: Type) => DataType<Array<Type>>, | ||
| Array8: <Type>(type: Type) => DataType<Array<Type>>, |
There was a problem hiding this comment.
If you call DataTypes.Array8(DataTypes.uint8), Type infers as DataType<number>, producing DataType<Array<DataType<number>>>. The actual runtime value is number[]. Should be:
Array0: <T>(type: DataType<T>) => DataType<Array<T>>
| data48: DataType<number>, | ||
| data56: DataType<number>, | ||
|
|
||
| bool: DataType<boolean>, |
There was a problem hiding this comment.
| bool: DataType<boolean>, | |
| bool: DataType<boolean | null>, |
| toJSON: () => T; | ||
| toBuffer: (buffer?: Buffer, index?: number) => Buffer; | ||
|
|
||
| class BitMap<Flags extends string | null> { |
There was a problem hiding this comment.
| class BitMap<Flags extends string | null> { | |
| class Bitmap<Flags extends string | null> { |
| map8 : <Flags extends string | null>(flags: Array<Flags>) => DataType<BitMap<Flags>>, | ||
| map16: <Flags extends string | null>(flags: Array<Flags>) => DataType<BitMap<Flags>>, | ||
| map24: <Flags extends string | null>(flags: Array<Flags>) => DataType<BitMap<Flags>>, | ||
| map32: <Flags extends string | null>(flags: Array<Flags>) => DataType<BitMap<Flags>>, | ||
| map40: <Flags extends string | null>(flags: Array<Flags>) => DataType<BitMap<Flags>>, | ||
| map48: <Flags extends string | null>(flags: Array<Flags>) => DataType<BitMap<Flags>>, | ||
| map56: <Flags extends string | null>(flags: Array<Flags>) => DataType<BitMap<Flags>>, | ||
| map64: <Flags extends string | null>(flags: Array<Flags>) => DataType<BitMap<Flags>>, |
There was a problem hiding this comment.
The PR types map8 as (flags: Array) - a single array argument. But node-zigbee calls it with spread args:
DataTypes.map8('flag1', 'flag2', 'flag3') // actual usage
DataTypes.map8(['flag1', 'flag2', 'flag3']) // what PR expects
Runtime accepts (...arg) so spread args is correct. The type should be:
map8: <Flags extends string | null>(...flags: Array<Flags>) => DataType<BitMap<Flags>>
| toBuffer: (buffer: Buffer, index?: number) => Buffer; | ||
| } | ||
|
|
||
| function Struct<Defs extends Record<string, DataType<any>>> (name: string, defs: Defs, opts?: {encodeMissingFieldsBehavior?: 'default' | 'skip'}): StaticStruct<Defs>; |
There was a problem hiding this comment.
The new generic parameter Defs extends Record<string, DataType<any>> is a breaking change for existing consumers. In node-zigbee, all Structs use the old pattern:
Struct<ZdoActiveEndpointsResponse>('name', { status: ZdoStatusCodesDataType, ... })
This passes the output type as the generic, not the defs record. With this change, TS errors on every single Struct call (17+ errors across zigbee and zstack packages).
| declare module "@athombv/data-types" { | ||
| interface DataTypeInterface { | ||
| declare module "@athombv/data-types" { | ||
| class DataType<Value> { |
There was a problem hiding this comment.
The DataType constructor is not exposed in the type declarations, but consumers create custom DataType instances directly. For example in node-zigbee's zdoStructs.mts:
new DataType(NaN, 'ZdoComplexDescriptor', 0, toBufFn, fromBufFn)
This currently errors with Expected 0 arguments, but got 5. The constructor needs to be declared:
constructor(id: number, shortName: string, length: number, toBuf: (...) => number, fromBuf: (...) => Value, ...args: unknown[]);
|
|
||
| type StructInstance<Defs extends Record<string, import('@athombv/data-types').DataType<any>>> = StructProperties<Defs> & { | ||
| toJSON: () => StructProperties<Defs>; | ||
| toBuffer: (buffer: Buffer, index?: number) => Buffer; |
There was a problem hiding this comment.
buffer should be optional here. The runtime allocates a buffer internally when called without arguments (toBuffer() with no args), and existing consumers rely on this:
const buf = instance.toBuffer(); // valid at runtime, errors with these types
Should be:
toBuffer: (buffer?: Buffer, index?: number) => Buffer;
| enum8 : <Flags extends string>(flags: Record<Flags, number>) => DataType<Flags>, | ||
| enum16: <Flags extends string>(flags: Record<Flags, number>) => DataType<Flags>, | ||
| enum32: <Flags extends string>(flags: Record<Flags, number>) => DataType<Flags>, |
There was a problem hiding this comment.
Same issue as the map types - the runtime uses (...arg) rest params, and some consumers spread additional args. In node-zigbee/zstack this causes TS2556: A spread argument must either have a tuple type or be passed to a rest parameter and TS2554: Expected 1 arguments, but got N errors.
The data types did not yet reflect the actual type of data they contained, so I made the class definition generic and added a new DataTypes definition using it.
I also took the liberty to rewrite the other definitions based on the types we have built at @athombv/drenso, based on the JS source and runtime introspection.