Best way to map types of two params of one function (And ensure type safety in the mapping type)
Problem Description:
I have a enum like this:
export enum testEnum {
key1 = "val1",
key2 = "val2"
}
and I have a function that the first param is testEnum
type, the second param will be some other type base on which enum was passed in the first param. And I use this:
testFunc<T extends `${testEnum}`>(
param1: T,
param2: paramMapType[T],
): Promise<void>
and a type use for mapping:
type paramMapType = {
val1: string;
val2: boolean
};
the problem now is that in paramMapType there are no type safety that the keys will be one of the values of testEnum
. I tried
type paramMapType = {
[key in `${testEnum}`]: any
val1: string;
val2: boolean
};
but got this err: A mapped type may not declare properties or methods.
How can I suppose to implement that kind of type safety in paramMapType
I used conditional type but it kind of long in syntax and yet have no type safety for the typeMap
Solution – 1
You can check, that there are only keys in the paramMapType
from the testEnum
enum by checking the type during type definition.
type paramMapType = Check<`${testEnum}`, {
val1: string;
val2: boolean
}>
The check will be implemented as follows:
type Check<Keys, Object> = Exclude<keyof Object, Keys> extends never ? Object : never
The check will return the same type in case there is no extra key in Object
that is not present in the enum.
Then, if you would redefine the type paramMapType
, for example like this:
type paramMapType = Check<`${testEnum}`, {
val1: string;
val2: boolean;
val3: number;
}>
The compiler would resolve the paramMapType
to never and then the second parameter of testFunc
would be never. As you can’t find an instance of never type, calling never with some literal value wouldn’t compile.