-
Notifications
You must be signed in to change notification settings - Fork 403
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
chore(store): add initial version of new strongly typed createSelector (
- Loading branch information
1 parent
5175b98
commit 90fdd58
Showing
2 changed files
with
184 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,156 @@ | ||
import { createSelector as createSelectorOrig } from '../utils/selector-utils'; | ||
import { SelectorDef, SelectorReturnType } from './selector-types.util'; | ||
|
||
type SelectorArg = SelectorDef<any>; | ||
|
||
type CreationMetadata = Parameters<typeof createSelectorOrig>[2]; | ||
|
||
// NOTE: This is temporarily named differently to `createSelector`, and | ||
// will be renamed when the types interface is finalised and publically exported. | ||
// Adding this here so that other dependent types can leverage this in the interim. | ||
export function createSelectorX< | ||
S1 extends SelectorArg, | ||
TProjector extends (s1: SelectorReturnType<S1>) => any | ||
>( | ||
selectors: [S1], | ||
projector: TProjector, | ||
creationMetadata?: Partial<CreationMetadata> | ||
): TProjector; | ||
|
||
export function createSelectorX< | ||
S1 extends SelectorArg, | ||
S2 extends SelectorArg, | ||
TProjector extends (s1: SelectorReturnType<S1>, s2: SelectorReturnType<S2>) => any | ||
>( | ||
selectors: [S1, S2], | ||
projector: TProjector, | ||
creationMetadata?: Partial<CreationMetadata> | ||
): TProjector; | ||
|
||
export function createSelectorX< | ||
S1 extends SelectorArg, | ||
S2 extends SelectorArg, | ||
S3 extends SelectorArg, | ||
TProjector extends ( | ||
s1: SelectorReturnType<S1>, | ||
s2: SelectorReturnType<S2>, | ||
s3: SelectorReturnType<S3> | ||
) => any | ||
>( | ||
selectors: [S1, S2, S3], | ||
projector: TProjector, | ||
creationMetadata?: Partial<CreationMetadata> | ||
): TProjector; | ||
|
||
export function createSelectorX< | ||
S1 extends SelectorArg, | ||
S2 extends SelectorArg, | ||
S3 extends SelectorArg, | ||
S4 extends SelectorArg, | ||
TProjector extends ( | ||
s1: SelectorReturnType<S1>, | ||
s2: SelectorReturnType<S2>, | ||
s3: SelectorReturnType<S3>, | ||
s4: SelectorReturnType<S4> | ||
) => any | ||
>( | ||
selectors: [S1, S2, S3, S4], | ||
projector: TProjector, | ||
creationMetadata?: Partial<CreationMetadata> | ||
): TProjector; | ||
|
||
export function createSelectorX< | ||
S1 extends SelectorArg, | ||
S2 extends SelectorArg, | ||
S3 extends SelectorArg, | ||
S4 extends SelectorArg, | ||
S5 extends SelectorArg, | ||
TProjector extends ( | ||
s1: SelectorReturnType<S1>, | ||
s2: SelectorReturnType<S2>, | ||
s3: SelectorReturnType<S3>, | ||
s4: SelectorReturnType<S4>, | ||
s5: SelectorReturnType<S5> | ||
) => any | ||
>( | ||
selectors: [S1, S2, S3, S4, S5], | ||
projector: TProjector, | ||
creationMetadata?: Partial<CreationMetadata> | ||
): TProjector; | ||
|
||
export function createSelectorX< | ||
S1 extends SelectorArg, | ||
S2 extends SelectorArg, | ||
S3 extends SelectorArg, | ||
S4 extends SelectorArg, | ||
S5 extends SelectorArg, | ||
S6 extends SelectorArg, | ||
TProjector extends ( | ||
s1: SelectorReturnType<S1>, | ||
s2: SelectorReturnType<S2>, | ||
s3: SelectorReturnType<S3>, | ||
s4: SelectorReturnType<S4>, | ||
s5: SelectorReturnType<S5>, | ||
s6: SelectorReturnType<S6> | ||
) => any | ||
>( | ||
selectors: [S1, S2, S3, S4, S5, S6], | ||
projector: TProjector, | ||
creationMetadata?: Partial<CreationMetadata> | ||
): TProjector; | ||
|
||
export function createSelectorX< | ||
S1 extends SelectorArg, | ||
S2 extends SelectorArg, | ||
S3 extends SelectorArg, | ||
S4 extends SelectorArg, | ||
S5 extends SelectorArg, | ||
S6 extends SelectorArg, | ||
S7 extends SelectorArg, | ||
TProjector extends ( | ||
s1: SelectorReturnType<S1>, | ||
s2: SelectorReturnType<S2>, | ||
s3: SelectorReturnType<S3>, | ||
s4: SelectorReturnType<S4>, | ||
s5: SelectorReturnType<S5>, | ||
s6: SelectorReturnType<S6>, | ||
s7: SelectorReturnType<S7> | ||
) => any | ||
>( | ||
selectors: [S1, S2, S3, S4, S5, S6, S7], | ||
projector: TProjector, | ||
creationMetadata?: Partial<CreationMetadata> | ||
): TProjector; | ||
|
||
export function createSelectorX< | ||
S1 extends SelectorArg, | ||
S2 extends SelectorArg, | ||
S3 extends SelectorArg, | ||
S4 extends SelectorArg, | ||
S5 extends SelectorArg, | ||
S6 extends SelectorArg, | ||
S7 extends SelectorArg, | ||
S8 extends SelectorArg, | ||
TProjector extends ( | ||
s1: SelectorReturnType<S1>, | ||
s2: SelectorReturnType<S2>, | ||
s3: SelectorReturnType<S3>, | ||
s4: SelectorReturnType<S4>, | ||
s5: SelectorReturnType<S5>, | ||
s6: SelectorReturnType<S6>, | ||
s7: SelectorReturnType<S7>, | ||
s8: SelectorReturnType<S8> | ||
) => any | ||
>( | ||
selectors: [S1, S2, S3, S4, S5, S6, S7, S8], | ||
projector: TProjector, | ||
creationMetadata?: Partial<CreationMetadata> | ||
): TProjector; | ||
|
||
export function createSelectorX<T extends (...args: any[]) => any>( | ||
selectors: any[], | ||
projector: T, | ||
creationMetadata?: Partial<CreationMetadata> | ||
): T { | ||
return createSelectorOrig<T>(selectors, projector, <CreationMetadata>creationMetadata); | ||
} |
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,28 @@ | ||
import { StateToken } from '@ngxs/store'; | ||
import { StateClass } from '@ngxs/store/internals'; | ||
|
||
export type SelectorFunc<TModel> = (...arg: any[]) => TModel; | ||
|
||
export type TypedSelector<TModel> = StateToken<TModel> | SelectorFunc<TModel>; | ||
|
||
export type StateSelector = StateClass<any>; | ||
|
||
export type SelectorDef<TModel> = StateSelector | TypedSelector<TModel>; | ||
|
||
export type SelectorReturnType<T extends SelectorDef<any>> = T extends StateToken<infer R1> | ||
? R1 | ||
: T extends SelectorFunc<infer R2> | ||
? R2 | ||
: T extends StateClass<any> | ||
? any /* (Block comment to stop prettier breaking the comment below) | ||
// If the state selector is a class then we should infer its return type to `any`, and not to `unknown`. | ||
// Since we'll get an error that `Type 'unknown' is not assignable to type 'AuthStateModel'.` | ||
// The `unknown` type is not overridable when the strict mode is enabled: | ||
// function doSomethingWithArray(array: number[], factory: (x: unknown) => void) { | ||
// array.forEach(factory); | ||
// } | ||
// doSomethingWithArray([1, 2], (x: number) => console.log(x)); | ||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
// Type 'unknown' is not assignable to type 'number'. | ||
*/ | ||
: never; |