Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions src/vanilla/atom.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ export interface Atom<Value> {

export interface WritableAtom<Value, Args extends unknown[], Result>
extends Atom<Value> {
read: Read<Value, SetAtom<Args, Result>>
read: Read<Value, SetAtom<Args, unknown>>
write: Write<Args, Result>
onMount?: OnMount<Args, Result>
}
Expand All @@ -75,7 +75,7 @@ let keyCount = 0 // global key count for all atoms

// writable derived atom
export function atom<Value, Args extends unknown[], Result>(
read: Read<Value, SetAtom<Args, Result>>,
read: Read<Value, SetAtom<Args, unknown>>,
write: Write<Args, Result>,
): WritableAtom<Value, Args, Result>

Expand All @@ -98,7 +98,7 @@ export function atom<Value>(
): PrimitiveAtom<Value> & WithInitialValue<Value>

export function atom<Value, Args extends unknown[], Result>(
read?: Value | Read<Value, SetAtom<Args, Result>>,
read?: Value | Read<Value, SetAtom<Args, unknown>>,
write?: Write<Args, Result>,
) {
const key = `atom${++keyCount}`
Expand All @@ -110,7 +110,7 @@ export function atom<Value, Args extends unknown[], Result>(
},
} as WritableAtom<Value, Args, Result> & { init?: Value | undefined }
if (typeof read === 'function') {
config.read = read as Read<Value, SetAtom<Args, Result>>
config.read = read as Read<Value, SetAtom<Args, unknown>>
} else {
config.init = read
config.read = defaultRead
Expand Down
9 changes: 9 additions & 0 deletions tests/vanilla/types.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -67,3 +67,12 @@ it('type utils should work', () => {
}
expect(Component).toBeDefined()
})

it('WritableAtom Result type should be covariant', () => {
function Component() {
const writableAtom = atom(null, () => null)
Copy link
Member

Choose a reason for hiding this comment

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

This test doesn't represent your original reproduction. Can you do something similar to your repro in the PR description?

Copy link
Author

Choose a reason for hiding this comment

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

Which part of the original reproduction do you mean? () => null or [someArg: number]?

The someArg was actually a mistake. That wouldn't be assignable anyway (the arguments should be contravariant). I fixed the example in my local reproduction and updated the PR description

Copy link
Member

Choose a reason for hiding this comment

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

I mean in this case, we could do:

Suggested change
const writableAtom = atom(null, () => null)
const writableAtom = atom(null, () => null as null | number)

I think we need the actual case in the test:

export const createWritableAtom = (): WritableAtom<
  null,
  [],
  number | null
> =>
  atom(
    () => null,
    (get, set, someArg: string) => {
      return null;
    },
  );

Copy link
Member

Choose a reason for hiding this comment

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

☝️ Does it make sense?


expectType<WritableAtom<null, [], number | null>>(writableAtom)
}
expect(Component).toBeDefined()
})