forked from DefinitelyTyped/DefinitelyTyped
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Moshe Kolodny
committed
May 26, 2020
1 parent
c3ba003
commit 7bae698
Showing
4 changed files
with
296 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
// Type definitions for recoil 0.0 | ||
// Project: https://github.com/facebookexperimental/recoil#readme | ||
// Definitions by: Moshe Kolodny <https://github.com/kolodny> | ||
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped | ||
|
||
import React = require('react'); | ||
|
||
export {}; | ||
|
||
type Getter = <U>(u: RecoilValue<U>) => U; | ||
type Setter = <U>(coil: RecoilValue<U>, value: U | ((u: U) => U)) => void; | ||
|
||
type SelectorGet<T> = (callback: { get: Getter }) => T; | ||
|
||
interface SelectorSet<U> { | ||
set: Setter; | ||
get: Getter; | ||
} | ||
|
||
interface SelectorParameter<T> { | ||
key: string; | ||
get: SelectorGet<T>; | ||
set?: <U extends T>(options: SelectorSet<U>, newValue: U) => void; | ||
} | ||
|
||
export const RecoilRoot: React.ComponentType; | ||
|
||
interface Atom<T> { | ||
readonly __type__: unique symbol; | ||
key: string; | ||
} | ||
|
||
interface Selector<T> { | ||
readonly __type__: unique symbol; | ||
key: string; | ||
} | ||
|
||
type RecoilValue<T> = Atom<T> | Selector<T>; | ||
|
||
export function atom<T>(options: { key: string; default: T }): Atom<T>; | ||
export function selector<T>(options: SelectorParameter<T>): Selector<T>; | ||
|
||
export function isRecoilValue(x: any): x is RecoilValue<any>; | ||
|
||
type ReactState<T> = [T, React.Dispatch<React.SetStateAction<T>>]; | ||
|
||
export function useRecoilState<T>(recoilValue: RecoilValue<T>): ReactState<T>; | ||
export function useRecoilValue<T>(recoilValue: RecoilValue<T>): ReactState<T>[0]; | ||
export function useSetRecoilState<T>(recoilValue: RecoilValue<T>): ReactState<T>[1]; | ||
|
||
export function useResetRecoilState(recoilValue: RecoilValue<any>): () => void; | ||
|
||
type Loadable<T> = | ||
| { | ||
state: 'hasValue'; | ||
contents: T; | ||
getValue: () => Promise<T>; | ||
toPromise: () => Promise<T>; | ||
} | ||
| { | ||
state: 'loading'; | ||
contents: Promise<T>; | ||
/** When state is 'loading' getValue throws a Promise */ | ||
getValue: () => never; | ||
toPromise: () => Promise<T>; | ||
} | ||
| { | ||
state: 'hasError'; | ||
contents: Error; | ||
/** When state is 'hasError' getValue() throws the error */ | ||
getValue: () => never; | ||
toPromise: () => Promise<never>; | ||
}; | ||
export function useRecoilValueLoadable<T>(recoilValue: RecoilValue<T>): Loadable<T>; | ||
export function useRecoilStateLoadable<T>(recoilValue: RecoilValue<T>): [Loadable<T>, ReactState<T>]; | ||
|
||
interface CallbackInterface { | ||
getPromise: <T>(recoilValue: RecoilValue<T>) => Promise<T>; | ||
getLoadable: <T>(recoilValue: RecoilValue<T>) => Loadable<T>; | ||
set: Setter; | ||
reset: (recoilValue: RecoilValue<any>) => void; | ||
} | ||
|
||
export function useRecoilCallback(callback: (callbackInterface: CallbackInterface) => void): () => void; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,187 @@ | ||
import { | ||
atom, | ||
selector, | ||
useRecoilState, | ||
useRecoilCallback, | ||
isRecoilValue, | ||
useResetRecoilState, | ||
useRecoilValue, | ||
useSetRecoilState, | ||
useRecoilValueLoadable, | ||
useRecoilStateLoadable, | ||
} from 'recoil'; | ||
|
||
function describe(desc: string, fn: () => void) {} | ||
function it(desc: string, fn: () => void) {} | ||
|
||
describe('atom', () => { | ||
it('has a key prop', () => { | ||
const a = atom({ | ||
key: 'a', | ||
default: '123', | ||
}); | ||
a; // $ExpectType Atom<string> | ||
a.key; // $ExpectType string | ||
}); | ||
}); | ||
|
||
describe('selector', () => { | ||
it('has a get prop', () => { | ||
const s = selector({ | ||
key: 's', | ||
get: () => 123 | ||
}); | ||
s; // $ExpectType Selector<number> | ||
s.key; // $ExpectType string | ||
}); | ||
|
||
// Yo dawg | ||
it('gets the `get` callback to get', () => { | ||
const a = atom({ key: 'a', default: 123 }); | ||
const s = selector({ | ||
key: 's', | ||
get: ({ get }) => { | ||
const got = get(a); // $ExpectType number | ||
return `${got}`; | ||
} | ||
}); | ||
s; // $ExpectType Selector<string> | ||
}); | ||
|
||
it('gets the `get` callback to set', () => { | ||
const a = atom({ key: 'a', default: 123 }); | ||
const s = selector({ | ||
key: 's', | ||
get: () => 123, | ||
set: ({ get }) => { | ||
const got = get(a); // $ExpectType number | ||
} | ||
}); | ||
}); | ||
|
||
it('gets the `set` callback to set', () => { | ||
const a = atom({ key: 'a', default: 123 }); | ||
const s = selector({ | ||
key: 's', | ||
get: () => 123, | ||
set: ({ set }) => { | ||
set(a, '123'); // $ExpectError | ||
set(a, 321); | ||
} | ||
}); | ||
}); | ||
}); | ||
|
||
describe('atom <-> selector uniqueness', () => { | ||
it(`can't assign atom to selector or vice versa`, () => { | ||
let a = atom({ key: 'a', default: '123' }); | ||
let s = selector({ key: 'a', get: () => '123' }); | ||
a = s; // $ExpectError | ||
s = a; // $ExpectError | ||
}); | ||
}); | ||
|
||
describe('useRecoilState', () => { | ||
it('works on atoms', () => { | ||
const a = atom({ key: 'a', default: '123' }); | ||
const [aState, setAState] = useRecoilState(a); | ||
aState; // $ExpectType string | ||
setAState; // $ExpectType Dispatch<SetStateAction<string>> | ||
}); | ||
}); | ||
|
||
describe('useRecoilValue', () => { | ||
it('works on atoms', () => { | ||
const a = atom({ key: 'a', default: '123' }); | ||
const aState = useRecoilValue(a); | ||
aState; // $ExpectType string | ||
}); | ||
}); | ||
|
||
describe('useSetRecoilState', () => { | ||
it('works on atoms', () => { | ||
const a = atom({ key: 'a', default: '123' }); | ||
const setAState = useSetRecoilState(a); | ||
setAState; // $ExpectType Dispatch<SetStateAction<string>> | ||
}); | ||
}); | ||
|
||
describe('isRecoilValue', () => { | ||
it('is a typeguard', () => { | ||
const x = {} as any; | ||
if (isRecoilValue(x)) { | ||
x; // $ExpectType RecoilValue<any> | ||
} | ||
}); | ||
}); | ||
|
||
describe('useResetRecoilState', () => { | ||
it('is a void fn', () => { | ||
const a = atom({ key: 'a', default: '123' }); | ||
const fn = useResetRecoilState(a); | ||
fn; // $ExpectType () => void | ||
}); | ||
}); | ||
|
||
describe('useRecoilValueLoadable', () => { | ||
it(`has a 'hasValue' state`, () => { | ||
const a = atom({ key: 'a', default: '123' }); | ||
const loadableState = useRecoilValueLoadable(a); | ||
if (loadableState.state === 'hasValue') { | ||
loadableState.contents; // $ExpectType string | ||
loadableState.getValue; // $ExpectType () => Promise<string> | ||
loadableState.state; // $ExpectType "hasValue" | ||
loadableState.toPromise; // $ExpectType () => Promise<string> | ||
} | ||
}); | ||
|
||
it(`has a 'loading' state`, () => { | ||
const a = atom({ key: 'a', default: '123' }); | ||
const loadableState = useRecoilValueLoadable(a); | ||
if (loadableState.state === 'loading') { | ||
loadableState.contents; // $ExpectType Promise<string> | ||
|
||
// DocComment should be: "When state is 'loading' getValue throws a Promise<T>" | ||
loadableState.getValue; // $ExpectType () => never | ||
loadableState.state; // $ExpectType "loading" | ||
loadableState.toPromise; // $ExpectType () => Promise<string> | ||
} | ||
}); | ||
|
||
it(`has a 'hasError' state`, () => { | ||
const a = atom({ key: 'a', default: '123' }); | ||
const loadableState = useRecoilValueLoadable(a); | ||
if (loadableState.state === 'hasError') { | ||
loadableState.contents; // $ExpectType Error | ||
// DocComment should be: "When state is 'hasError' getValue() throws the error" | ||
loadableState.getValue; // $ExpectType () => never | ||
loadableState.state; // $ExpectType "hasError" | ||
loadableState.toPromise; // $ExpectType () => Promise<never> | ||
} | ||
}); | ||
}); | ||
|
||
describe('useRecoilValueLoadable', () => { | ||
it(`has a 'hasValue' state`, () => { | ||
const a = atom({ key: 'a', default: '123' }); | ||
const [loadableState, [state, setState]] = useRecoilStateLoadable(a); | ||
|
||
// See `useRecoilValueLoadable` suite above for better tests. | ||
loadableState; // $ExpectType Loadable<string> | ||
|
||
state; // $ExpectType string | ||
setState; // $ExpectType Dispatch<SetStateAction<string>> | ||
}); | ||
}); | ||
|
||
describe('useRecoilCallback', () => { | ||
it('gets the correct arguments in the callback', () => { | ||
const itemsInCart = atom({ key: 'a', default: 123 }); | ||
const logCartItems = useRecoilCallback(async ({getPromise}) => { | ||
const numItemsInCart = await getPromise(itemsInCart); // $ExpectType number | ||
|
||
/* console.log( */ `items in cart: ${numItemsInCart}` /* ) */; | ||
}); | ||
logCartItems; // $ExpectType () => void | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
{ | ||
"compilerOptions": { | ||
"module": "commonjs", | ||
"lib": [ | ||
"es6" | ||
], | ||
"noImplicitAny": true, | ||
"noImplicitThis": true, | ||
"strictFunctionTypes": true, | ||
"strictNullChecks": true, | ||
"baseUrl": "../", | ||
"typeRoots": [ | ||
"../" | ||
], | ||
"types": [], | ||
"noEmit": true, | ||
"forceConsistentCasingInFileNames": true, | ||
"esModuleInterop": true | ||
}, | ||
"files": [ | ||
"index.d.ts", | ||
"recoil-tests.ts" | ||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
{ "extends": "dtslint/dt.json" } |