diff --git a/.changeset/makepersisted-type-inference-fix.md b/.changeset/makepersisted-type-inference-fix.md new file mode 100644 index 000000000..3e5cdda32 --- /dev/null +++ b/.changeset/makepersisted-type-inference-fix.md @@ -0,0 +1,5 @@ +--- +"@solid-primitives/storage": patch +--- + +fix: restore `makePersisted` generic type inference under TypeScript 5+/7. Calling `makePersisted(createSignal("hello"), { name, storage: localStorage })` previously fell back to `T = unknown` and errored with `TS2769`. The public overloads now extract `T` from `S` via `SignalType` (as in 4.3.5). diff --git a/packages/storage/src/persisted.ts b/packages/storage/src/persisted.ts index ad814bd2c..77e09691f 100644 --- a/packages/storage/src/persisted.ts +++ b/packages/storage/src/persisted.ts @@ -70,6 +70,11 @@ export type PersistenceOptions | undefined> = { storageOptions?: O; }); +export type SignalInput = Signal | [Store, SetStoreFunction]; + +export type SignalType = + S extends Signal ? T : S extends [Store, SetStoreFunction] ? T : never; + export type PersistedState = S & { 2: Promise | string | null }; /** @@ -92,19 +97,18 @@ export type PersistedState = S & { 2: Promise | string | null }; * @param {PersistenceOptions} options - The options for persistence. * @returns {PersistedState} - The persisted signal or store. */ -export function makePersisted | [Store, SetStoreFunction]>( +export function makePersisted( signal: S, - options?: PersistenceOptions, + options?: PersistenceOptions, undefined>, +): PersistedState; +export function makePersisted>( + signal: S, + options: PersistenceOptions, O>, ): PersistedState; export function makePersisted< - T, - S extends Signal | [Store, SetStoreFunction], - O extends Record, ->(signal: S, options: PersistenceOptions): PersistedState; -export function makePersisted< - T, - S extends Signal | [Store, SetStoreFunction], + S extends SignalInput, O extends Record | undefined, + T = SignalType, >( signal: S, options: PersistenceOptions = {} as PersistenceOptions, diff --git a/packages/storage/test/persisted.test.ts b/packages/storage/test/persisted.test.ts index 06ea9137a..883a25795 100644 --- a/packages/storage/test/persisted.test.ts +++ b/packages/storage/test/persisted.test.ts @@ -141,4 +141,16 @@ describe("makePersisted", () => { }); expect(init).toBe(promise); }); + it("infers the signal value type from the input without explicit annotations", () => { + // Regression test for solid-primitives#1000: under TypeScript 5+/7 the + // overloads previously defaulted T to `unknown` instead of inferring it + // from the input signal/store, breaking inference at the call site. + const [thing, setThing] = makePersisted(createSignal("hello"), { + name: "thing", + storage: mockStorage, + }); + const _a: string = thing(); + const _b: string = setThing("world"); + expect(thing()).toBe("world"); + }); });