diff --git a/ably.d.ts b/ably.d.ts index cd60057e7..eaccb3ccb 100644 --- a/ably.d.ts +++ b/ably.d.ts @@ -2105,10 +2105,12 @@ export declare interface LiveMap extends LiveObject(key: TKey): T[TKey] extends StateValue ? T[TKey] : T[TKey] | undefined; + get(key: TKey): T[TKey] | undefined; /** * Returns the number of key/value pairs in the map. diff --git a/src/plugins/liveobjects/livemap.ts b/src/plugins/liveobjects/livemap.ts index 7271beb5b..b6899c2b7 100644 --- a/src/plugins/liveobjects/livemap.ts +++ b/src/plugins/liveobjects/livemap.ts @@ -78,6 +78,7 @@ export class LiveMap extends LiveObject extends LiveObject(key: TKey): T[TKey] extends StateValue ? T[TKey] : T[TKey] | undefined { + get(key: TKey): T[TKey] | undefined { + if (this.isTombstoned()) { + return undefined as T[TKey]; + } + const element = this._dataRef.data.get(key); if (element === undefined) { diff --git a/test/package/browser/template/src/index-liveobjects.ts b/test/package/browser/template/src/index-liveobjects.ts index 00763d46b..4059cc01d 100644 --- a/test/package/browser/template/src/index-liveobjects.ts +++ b/test/package/browser/template/src/index-liveobjects.ts @@ -24,14 +24,14 @@ globalThis.testAblyPackage = async function () { const size: number = root.size(); // check custom user provided typings via LiveObjectsTypes are working: + // any LiveMap.get() call can return undefined, as the LiveMap itself can be tombstoned (has empty state), + // or referenced object is tombstoned. // keys on a root: - const aNumber: number = root.get('numberKey'); - const aString: string = root.get('stringKey'); - const aBoolean: boolean = root.get('booleanKey'); - const couldBeUndefined: string | undefined = root.get('couldBeUndefined'); + const aNumber: number | undefined = root.get('numberKey'); + const aString: string | undefined = root.get('stringKey'); + const aBoolean: boolean | undefined = root.get('booleanKey'); + const userProvidedUndefined: string | undefined = root.get('couldBeUndefined'); // live objects on a root: - // LiveMap.get can still return undefined for LiveObject typed properties even if custom typings have them as non-optional. - // objects can be tombstoned and result in the undefined value const counter: Ably.LiveCounter | undefined = root.get('counterKey'); const map: LiveObjectsTypes['root']['mapKey'] | undefined = root.get('mapKey'); // check string literal types works @@ -63,5 +63,5 @@ globalThis.testAblyPackage = async function () { // check can provide custom types for the getRoot method, ignoring global LiveObjectsTypes interface const explicitRoot: Ably.LiveMap = await liveObjects.getRoot(); - const someOtherKey: string = explicitRoot.get('someOtherKey'); + const someOtherKey: string | undefined = explicitRoot.get('someOtherKey'); };