Skip to content

Commit 955430d

Browse files
authored
fix(atoms): move override to AtomTemplateBase for NodeOf<->AnyAtomInstance interop (#343)
1 parent 84a44a6 commit 955430d

File tree

2 files changed

+35
-0
lines changed

2 files changed

+35
-0
lines changed

packages/atoms/src/classes/templates/AtomTemplateBase.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,10 @@ export abstract class AtomTemplateBase<
8080
params: G['Params']
8181
): G['Node']
8282

83+
public override(_newValue: any): any {
84+
return undefined as any // subclasses must override this
85+
}
86+
8387
public getNodeId(
8488
ecosystem: Ecosystem,
8589
params?: G['Params'],

packages/react/test/types.test.tsx

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -688,6 +688,37 @@ describe('react types', () => {
688688
expectTypeOf<typeof val2>().toBeString()
689689
})
690690

691+
test('override method on AnyAtomTemplate and AnyAtomInstance.t', () => {
692+
// AnyAtomTemplate should have the override method
693+
const overrideAny = <A extends AnyAtomTemplate>(template: A) =>
694+
template.override(() => 'new value')
695+
696+
// AnyAtomInstance.t should also have override (since .t is AtomTemplateBase)
697+
const overrideFromInstance = <I extends AnyAtomInstance>(instance: I) =>
698+
instance.t.override(() => 'new value')
699+
700+
// NodeOf should produce instances whose .t has override and is
701+
// assignable to AnyAtomTemplate
702+
type ExampleNode = NodeOf<typeof exampleAtom>
703+
const templateFromNode = <I extends ExampleNode>(instance: I) =>
704+
instance.t.override(() => 'new value')
705+
706+
// A function accepting AnyAtomTemplate should accept .t from NodeOf
707+
const acceptTemplate = (t: AnyAtomTemplate) => t.key
708+
const useTemplate = (instance: ExampleNode) => acceptTemplate(instance.t)
709+
710+
// Inverse: AnyAtomTemplate should be passable where NodeOf<atom>.t is expected
711+
const acceptSpecificTemplate = (t: ExampleNode['t']) => t.key
712+
const useAnyTemplate = (t: AnyAtomTemplate) => acceptSpecificTemplate(t)
713+
714+
const instance = ecosystem.getInstance(exampleAtom, ['a'])
715+
overrideAny(exampleAtom)
716+
overrideFromInstance(instance)
717+
templateFromNode(instance)
718+
useTemplate(instance)
719+
useAnyTemplate(exampleAtom)
720+
})
721+
691722
test('injectors', () => {
692723
const injectingAtom = atom('injecting', () => {
693724
// @ts-expect-error missing param

0 commit comments

Comments
 (0)