Is there a generic way to pass into a constructor all the key
s and what each data
is returned by each key by all the functions within?
Currently I do this:
class Redis {
get() {
}
set() {
}
// ... many more methods
}
const redis = new Redis();
type IEmailKey = `unverified-email:${number}`;
type IEmailData = string;
type IDidRemindKey = `did-remind:${number}`;
type IDidRemindData = boolean;
type IStrictGet = {
(key: IEmailKey): Promise<IEmailData | null>;
(key: IDidRemindKey): Promise<IDidRemindData | null>;
};
type IRedisSetParams = Parameters<Redis['set']>;
type IStrictSet = {
(
key: IEmailKey,
value: IEmailData,
options?: IRedisSetParams[2]
): Promise<'OK' | null>;
(
key: IDidRemindKey,
value: IDidRemindData,
options?: IRedisSetParams[2]
): Promise<'OK' | null>;
};
// This has key's typed along with the type of data each key contains.
type IStrictRedis = Omit<Redis, 'get' | 'set'> & {
get: IStrictGet;
set: IStrictSet;
};
This allows me to do redis.get('unverified-email:123')
and redis.set('unverified-email:123', '[email protected]')
and redis.get('did-remind:123')
and redis.set('did-remind:123', true)
.
I was hoping for a simple way to pass generic to class Redis
which handles it, here is pseudocode:
const redis = new Redis<{
[`unverified-email:${number}`]: string;
[`did-remind:${number}`]: boolean;
}>();
CodePudding user response:
You could declare Redis
like this:
class Redis<T extends Record<string, any>> {
get<K extends keyof T>(key: K): T[K] {
return {} as any
}
set<K extends keyof T, V extends T[K]>(key: K, value: V): Promise<'OK' | null> {
return {} as any
}
}
And construct it similiar to what your pseudcode looked like. Only difference here is that we have to prepend key:
before the string literal.
const redis = new Redis<{
[key: `unverified-email:${number}`]: string
[key: `did-remind:${number}`]: boolean
}>();
Some test-cases:
const a = redis.get("unverified-email:123")
// ^? const a: string
const b = redis.get("did-remind:1")
// ^? const b: boolean
redis.set("unverified-email:123", "abc")
redis.set("did-remind:1", true)
redis.set("unverified-eail:123", "abc") // Error: "unverified-eail:123"' is not assignable to parameter of type '`unverified-email:${number}`
redis.set("did-remind:1", "abc") // Error: Argument of type 'string' is not assignable to parameter of type 'boolean'