For the purposes of demonstration, consider the following types:
type ToEnglish<A extends string> =
A extends "1" ? "one" :
A extends "2" ? "two" :
A extends "3" ? "three" :
"etc";
type Convert<A extends string> =
A extends `${infer C}${infer Tail}` ?
`${ToEnglish<C>}-${Convert<Tail>}` : "";
So for example, Convert<"12">
results in "one-two-"
.
Now I would like to make it more generic and accept a "translator" such as ToEnglish
above as an argument:
type Convert2<A extends string, Translator> =
A extends `${infer C}${infer Tail}` ?
`${Translator<C>}-${Convert<Tail>}` : "";
This won't work: Type 'Translator' is not generic. ts(2315)
If I try to write:
type Convert3<A extends string, Translator<_>> =
I get: ',' expected. ts(1005)
at the <_>
.
Q:
Is there a way to pass a parametric (generic) type as an argument (parameter) to another type somehow in TypeScript, Flow, or another JavaScript superset?
Similar to higher-order functions, but for types.
I'd suggest a solution that bypasses having to pass the generic type as a type parameter directly. For instance, by using what is essentially a record of translators, you can instead pass the name of a given translator and access the type:
type ToEnglish<A extends string> =
A extends "1" ? "one" :
A extends "2" ? "two" :
A extends "3" ? "three" :
"etc";
type ToSpanish<A extends string> =
A extends "1" ? "uno" :
A extends "2" ? "dos" :
A extends "3" ? "tres" :
"etc";
type TranslatorMap<A extends string> = {
English: ToEnglish<A>;
Spanish: ToSpanish<A>;
}
type ConvertGeneric<A extends string, Translator extends keyof TranslatorMap<A>> =
A extends `${infer C}${infer Tail}` ?
`${TranslatorMap<C>[Translator]}-${ConvertGeneric<Tail, Translator>}` : "";
type EnglishTest = ConvertGeneric<"12", "English">
type SpanishTest = ConvertGeneric<"12", "Spanish">