diff --git a/package.json b/package.json index 94123f577..b6ea9ee0d 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,7 @@ ], "resolutions": { "jest": "^29.5.0", - "typescript": "^5.6.2", + "typescript": "^5.9.2", "recast": "^0.23.1" }, "repository": { @@ -68,7 +68,7 @@ "tape": "^5.0.1", "ts-jest": "^29.0.5", "tsdx": "^0.14.1", - "typescript": "^5.6.2" + "typescript": "^5.9.2" }, "husky": { "hooks": { diff --git a/packages/mobx/__tests__/v5/base/typescript-tests.ts b/packages/mobx/__tests__/v5/base/typescript-tests.ts index e7a3a510e..8c17f046d 100644 --- a/packages/mobx/__tests__/v5/base/typescript-tests.ts +++ b/packages/mobx/__tests__/v5/base/typescript-tests.ts @@ -1933,6 +1933,44 @@ test("allow 'as const' for creating tuples for observable.map()", () => { mobx.observable.map(newValues) }) +test("infers tuple type for observable.map() when using array.map", () => { + interface Usage { + daily: number + monthly: number + } + const data: Array<{ id: string; usage: Usage }> = [ + { id: "1", usage: { daily: 5, monthly: 100 } }, + { id: "2", usage: { daily: 10, monthly: 200 } }, + { id: "3", usage: { daily: 15, monthly: 300 } } + ] + + const map = mobx.observable.map( + data.map(app => [app.id, app.usage]), + { name: "test" } + ) + + expect(map.get("2")).toEqual({ daily: 10, monthly: 200 }) +}) + +test("observable.map() accepts an undefined value with or without options", () => { + const map = mobx.observable.map(undefined, { name: "custom name" }) + map.set("test", 1) + expect(map.get("test")).toBe(1) + expect(map.name_).toBe("custom name") + + // without options + mobx.observable.map(undefined) +}) + +test("observable.map() accepts optional initial values", () => { + interface Usage {} + + ;(data?: [string, Usage][]) => observable.map(data, { name: "test" }) + ;(data?: readonly (readonly [string, Usage])[]) => observable.map(data, { name: "test" }) + ;(data?: Record) => observable.map(data, { name: "test" }) + ;(data?: Map) => observable.map(data, { name: "test" }) +}) + test("toJS bug #1413 (TS)", () => { class X { test = { diff --git a/packages/mobx/src/api/observable.ts b/packages/mobx/src/api/observable.ts index 47a77c248..738410ea6 100644 --- a/packages/mobx/src/api/observable.ts +++ b/packages/mobx/src/api/observable.ts @@ -3,6 +3,9 @@ import { IEqualsComparer, IObservableArray, IObservableMapInitialValues, + IMapEntries, + IReadonlyMapEntries, + IKeyValueMap, IObservableSetInitialValues, IObservableValue, ObservableMap, @@ -151,6 +154,24 @@ export interface IObservableValueFactory { (value?: T, options?: CreateObservableOptions): IObservableValue } +export interface IObservableMapFactory { + (): ObservableMap + (initialValues?: IMapEntries, options?: CreateObservableOptions): ObservableMap< + K, + V + > + ( + initialValues?: IReadonlyMapEntries, + options?: CreateObservableOptions + ): ObservableMap + (initialValues?: IKeyValueMap, options?: CreateObservableOptions): ObservableMap + (initialValues?: Map, options?: CreateObservableOptions): ObservableMap + (initialValues: undefined, options?: CreateObservableOptions): ObservableMap< + K, + V + > +} + export interface IObservableFactory extends Annotation, PropertyDecorator, @@ -172,10 +193,7 @@ export interface IObservableFactory initialValues?: IObservableSetInitialValues, options?: CreateObservableOptions ) => ObservableSet - map: ( - initialValues?: IObservableMapInitialValues, - options?: CreateObservableOptions - ) => ObservableMap + map: IObservableMapFactory object: ( props: T, decorators?: AnnotationsMap, diff --git a/packages/mobx/src/types/observablemap.ts b/packages/mobx/src/types/observablemap.ts index e47eead41..014b65507 100644 --- a/packages/mobx/src/types/observablemap.ts +++ b/packages/mobx/src/types/observablemap.ts @@ -46,7 +46,7 @@ export interface IKeyValueMap { export type IMapEntry = [K, V] export type IReadonlyMapEntry = readonly [K, V] export type IMapEntries = IMapEntry[] -export type IReadonlyMapEntries = IReadonlyMapEntry[] +export type IReadonlyMapEntries = readonly IReadonlyMapEntry[] export type IMapDidChange = { observableKind: "map"; debugObjectName: string } & ( | { diff --git a/yarn.lock b/yarn.lock index f4cf053ae..00d2cd90c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -13778,10 +13778,10 @@ typedarray@^0.0.6: resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" integrity sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA== -typescript@^3.7.3, typescript@^5.6.2: - version "5.6.2" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.6.2.tgz#d1de67b6bef77c41823f822df8f0b3bcff60a5a0" - integrity sha512-NW8ByodCSNCwZeghjN3o+JX5OFH0Ojg6sadjEKY4huZ52TqbJTJnDo5+Tw98lSy63NZvi4n+ez5m2u5d4PkZyw== +typescript@^3.7.3, typescript@^5.9.2: + version "5.9.2" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.9.2.tgz#d93450cddec5154a2d5cabe3b8102b83316fb2a6" + integrity sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A== uglify-js@^3.1.4: version "3.17.4"