Skip to content

Add TypeScript type declarations#15

Closed
mabahamo wants to merge 12 commits intomeshcore-dev:masterfrom
mabahamo:add-typescript-declarations
Closed

Add TypeScript type declarations#15
mabahamo wants to merge 12 commits intomeshcore-dev:masterfrom
mabahamo:add-typescript-declarations

Conversation

@mabahamo
Copy link

Adds TypeScript type declarations to support TS projects using this library.

Changes

  • Add index.d.ts with type definitions for exported classes
  • Update package.json with types field

What's included

Types for:

  • Connection classes (Connection, NodeJSSerialConnection, WebSerialConnection, TCPConnection, etc.)
  • Constants, Advert, Packet, BufferUtils, CayenneLpp
  • Submodules: constants.js, buffer_reader.js, buffer_writer.js

Tested with a TypeScript project, types correctly resolve for the main API methods.

- Add index.d.ts with comprehensive type definitions for all exported classes
- Include type declarations for Connection, NodeJSSerialConnection, and other connection types
- Add types for Constants, Advert, Packet, BufferUtils, and CayenneLpp
- Add type declarations for submodules (constants, buffer_reader, buffer_writer)
- Update package.json to reference the types file

This enables TypeScript users to have proper type checking and autocomplete when using the library.
@everett1992
Copy link

What about migrating to typescript, or tsc with jsdoc comments? It will be easier to ensure there is no drift with the .d.ts files.

index.d.ts Outdated
syncNextMessage(): Promise<void>;

// Message sending
sendTextMessage(publicKey: Buffer, text: string): Promise<void>;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think Unit8Array would be better than Buffer - Buffer comes from node and isn't a web standard. Buffer extends Uint8Array

index.d.ts Outdated
// Events
on(event: 'connected', listener: () => void): this;
on(event: 'disconnected', listener: () => void): this;
on(event: number, listener: (data: any) => void): this;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we do better than any?

I'm not actually familiar with the event API, but we can use numeric and string literal overrides

on(event: MsgWaiting, (msg: MsgWaitingArgs):this
on(event: OtherEvent, (msg: OtherEventArgs): :this

index.d.ts Outdated
}

export class NodeJSSerialConnection extends Connection {
constructor(port: string);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doc comments on types are really useful, they appear in IDE hover/go-to-definition which usually finds .d.ts files instead of .js files.

I won't recommend copying them all from .js to .d.ts, that's just more data that can get out of sync. But it's another reason to move to native typescript.

index.d.ts Outdated

// Type definitions
export interface SelfInfo {
publicKey: Buffer;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

type, txPower, maxTxPower, publicKey, advLat, advLogn, reserved, manualAddContacts, radioFreq, radioBw, radioSf, radioCr, name

type: bufferReader.readByte(),
txPower: bufferReader.readByte(),
maxTxPower: bufferReader.readByte(),
publicKey: bufferReader.readBytes(32),
advLat: bufferReader.readInt32LE(),
advLon: bufferReader.readInt32LE(),
reserved: bufferReader.readBytes(3),
manualAddContacts: bufferReader.readByte(),
radioFreq: bufferReader.readUInt32LE(),
radioBw: bufferReader.readUInt32LE(),
radioSf: bufferReader.readByte(),
radioCr: bufferReader.readByte(),
name: bufferReader.readString(),

index.d.ts Outdated
pubKeyPrefix: Buffer;
pathLen: number;
txtType: number;
senderTimestamp: number;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NIT: Use type alias's to give names to string-ish or number-ish things. It doesn't add any overhead (it's still just a number) but adds some documentation.

type EpochSeconds = number

senderTimestamp: EpochSeconds

index.d.ts Outdated
name?: string;
}

export interface Message {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a ContactMessage

index.d.ts Outdated
text: string;
}

export interface Channel {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NIT ChannelInfo?

index.d.ts Outdated
secret: Buffer;
}

export interface Contact {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing contact fields

index.d.ts Outdated
static readonly SupportedCompanionProtocolVersion: number;

static readonly ResponseCodes: {
ContactMsgRecv: number;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

List all the constants, and use the number literals. Unfortunatly that basically means copying the whole constants file.

index.d.ts Outdated
}

// Type declarations for submodules
declare module '@liamcottle/meshcore.js/src/constants.js' {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are you defining these sub-module exports? constants is exported from the index, buf reader & writer are not, and I'm assuming that's by design?

- Delete hand-written index.d.ts that drifted from source
- Add JSDoc type annotations to all source files
- Create src/types.js with shared typedefs (SelfInfo, Contact,
  ContactMessage, ChannelInfo, RepeaterStats, etc.)
- Add tsconfig.json for declaration generation
- Add build:types script and prepublishOnly hook
- Add GitHub Actions CI workflow for type checking
- Use Uint8Array everywhere (no Buffer references)
- Add semantic type aliases (EpochSeconds, Milliseconds, MilliVolts)
- Add typed event overloads on Connection (on/once/off)
- All 11 PR meshcore-dev#15 review comments addressed
Keep setAutoAddContacts/setManualAddContacts passing true/false as
originally intended. Convert to 0/1 at the writeByte boundary using
a ternary operator.
…emove partial event overloads

- Restore behavioral descriptions for sendCommandExportContact and getNeighbours
- Use string literal union for AdvertParsedData.type and Advert.getTypeString()
- Remove on/once/off overrides that provided minimal type-safety value
@mabahamo mabahamo marked this pull request as draft February 18, 2026 09:35
…overloads

- Change TxtType from {number} to {0 | 1 | 2} literal union
- Add @type {const} to all Constants static properties for literal + readonly output
- Add JSDoc descriptions to all major typedefs for IDE hover tooltips
- Add typed event overloads to Connection.on() for all response/push events
- Fix sendCommandSendRawData path param from any[] to number[]
- Fix sendCommandSendRawData call site wrapping Uint8Array in unnecessary array
- Add missing event payload types (AdvertPush, PathUpdatedPush, OkResponse, etc.)
@mabahamo
Copy link
Author

What about migrating to typescript, or tsc with jsdoc comments? It will be easier to ensure there is no drift with the .d.ts files.

ok, I'll give it a shot to try to migrate it to typescript. I'll create a new PR.

@mabahamo mabahamo closed this Feb 19, 2026
@mabahamo mabahamo deleted the add-typescript-declarations branch February 20, 2026 23:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants