I would like to do something like:
namepace Namespace<S,T,U,V> {
type A = doSomething(S, T, U, V);
type B<X> = doSomethingB(type<A>, V, X);
interface I<X, Y> {
a: A;
b: B<X>
}
}
Basically I want to reuse generic arguments instead of repeating them everytime. I don't want to have to do something like:
type A<S, T, U, V> = doSomething(S, T, U, V);
type B<S, T, U, V, X> = doSomething(A<S, T, U, V>, V, X);
interface I<S, T, U, V, X> {
a: A<S, T, U, V>;
b: A<S, T, U, V, X>;
}
Another way to describe this is the equivalent of a nested typedef in C++:
template <typename T>
class Abc<T> {
template <typename U>
typedef myType<U> = MyFunctor<T, U>;
}
// This works
Abc<T>::myType<U> x;
As per @jcalz here is a self-contained example of the problem. Can't really make it minimal because the point is to have many types. What bothers me is all the type definitions, especially the helpers at the end, reusing the same arguments.
type BaseEngine<Player> = {players: Player[]}
export type CommandStruct<
Phase extends string,
MoveName extends string,
Player,
Engine extends BaseEngine<Player> = BaseEngine<Player>,
AvailableCommandData extends BaseCommandData<MoveName> = BaseCommandData<MoveName>,
CommandData extends BaseCommandData<MoveName> = BaseCommandData<MoveName>,
> = {
[phase in Phase]?: {
[move in MoveName]?: {
available: (engine: Engine, player: Player) => _AvailableCommandHelper<MoveName, AvailableCommandData, move>,
valid?: (move: _CommandHelper<MoveName, CommandData, move>, available: _AvailableCommandHelper<MoveName, AvailableCommandData, move>) => boolean
}
}
}
export type BaseCommandData<MoveName extends string> = {[key in MoveName]?: any};
export type AvailableCommands<MoveName extends string, AvailableCommandData extends BaseCommandData<MoveName>, PlayerId = number> = {
[move in MoveName]: _AvailableCommand<MoveName, AvailableCommandData, move, PlayerId>;
}
export type AvailableCommand<MoveName extends string, AvailableCommandData extends BaseCommandData<MoveName>, PlayerId = number> = AvailableCommands<MoveName, AvailableCommandData, PlayerId>[MoveName];
type _CommandHelper<MoveName extends string, CommandData extends BaseCommandData<MoveName>, move extends MoveName> = move extends keyof CommandData ? CommandData[move] : undefined;
type _AvailableCommandHelper<MoveName extends string, AvailableCommandData extends BaseCommandData<MoveName>, move extends MoveName> = move extends keyof AvailableCommandData ? AvailableCommandData[move] | AvailableCommandData[move][] | false : boolean;
type _AvailableCommand<MoveName extends string, AvailableCommandData extends BaseCommandData<MoveName>, move extends MoveName, PlayerId = number> = _CommandHelper<MoveName, AvailableCommandData, move> extends undefined ? {move: move, player: PlayerId} : {move: move, player: PlayerId, data: _AvailableCommandHelper<MoveName, AvailableCommandData, move>};