fix: types#801
Merged
Merged
Conversation
delucis
previously approved these changes
Sep 11, 2020
Member
delucis
left a comment
There was a problem hiding this comment.
Thanks! Do you want to have a go at integrating those helper types too? It’s a little tricky because you need to look-up moves in several places:
{
// top-level moves
moves: { /* ... */ },
turn: {
stages: {
[stage]: {
// stage-specific moves in top-level turn config
moves: { /* ... */ },
},
// ...
},
},
phases: {
[phase]: {
// phase-specific moves
moves: { /* ... */ },
turn: {
stages: {
[stage]: {
// stage-specific moves for this phase
moves: { /* ... */ },
},
// ...
},
},
},
// ...
},
};(The client creates the move dispatcher for all of these even when they’re not active, so it’s safe to statically type this.)
Contributor
Author
|
Cannot integrate those types into interface TicTacToeState {
cells: (number | null)[]
}
const clickCell = (G; TicTacToeState. ctx: Ctx, id: number) => {}
cosnt moves = { clickCell };
type TicTacToesMoves = {
[K in keyof typeof moves]: OmitArg<MoveMethod<typeof moves[K]>>;
};
export type TicTacToeBoardProps = BoardProps<TicTacToeState> & {
moves: TicTacToesMoves ;
}
export function TicTacToeBoard(props: TicTacToeBoardProps) {
// ....
} |
delucis
approved these changes
Sep 13, 2020
Member
delucis
left a comment
There was a problem hiding this comment.
It is actually possible to fully type a client’s moves map, combining your approach with some utility types from ts-toolbelt, but I’d need to think a little more about how best to integrate this into the clients themselves. Merging this in the meantime — thanks for the fixes!
import { O, U } from 'ts-toolbelt';
import {
Ctx,
Game,
LongFormMove,
Move,
MoveFn,
MoveMap,
PhaseConfig,
PhaseMap,
StageMap,
} from '../types';
/**
* Convert a move function to its dispatcher, stripping the G & ctx arguments.
* Dispatchers always return void.
*/
type OmitArgs<F> = F extends (G: any, ctx: Ctx, ...args: infer A) => any
? (...args: A) => void
: never;
/**
* Extract a move function from both short- and long-form move declarations.
*/
type MoveMethod<T extends Move> = T extends MoveFn
? T
: T extends LongFormMove
? T['move']
: never;
/**
* Extract a move dispatcher from its short- or long-form move declaration.
*/
type MoveDispatcher<T extends Move> = OmitArgs<MoveMethod<T>>;
/**
* Convert a map of move declarations to a map of move dispatchers.
*/
type MovesToDispatchers<T extends MoveMap> = {
[K in keyof T]: MoveDispatcher<T[K]>;
};
/**
* Extract a map of move dispatchers from a map of stage declarations.
*/
type StageDispatchers<T extends StageMap> = U.IntersectOf<
O.UnionOf<
{
[K in keyof T]: MovesToDispatchers<T[K]['moves']>;
}
>
>;
/**
* Extract a map of move dispatchers for a game’s top-level or a single phase.
*/
type DispatchersFromConfig<T extends PhaseConfig> = MovesToDispatchers<
T['moves']
> &
StageDispatchers<T['turn']['stages']>;
/**
* Extract a map of move dispatchers from a map of phase declarations.
*/
type PhaseDispatchers<T extends PhaseMap> = U.IntersectOf<
O.UnionOf<
{
[K in keyof T]: DispatchersFromConfig<T[K]>;
}
>
>;
/**
* Extract a map of move dispatchers from a game declaration.
*/
type DispatchersFromGame<T extends Game> = {} & DispatchersFromConfig<T> &
PhaseDispatchers<T['phases']>;
/**
* Example in use:
*/
const game = {
moves: {
foo: (G: any, ctx: Ctx, arg: number) => {},
},
turn: {
stages: {
A: {
moves: {
bar: () => {},
},
},
},
},
};
type ClientMoves = DispatchersFromGame<typeof game>;
// ClientMoves['foo'] = (arg: number) => void
// ClientMoves['bar'] = () => void
This file contains hidden or 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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Checklist
master).Other then that, these helper types may be helpful?
typescript playground