¿Cómo hacer cumplir las dependencias de tipo entre las propiedades de un objeto en los parámetros de una función de TypeScript?
Estoy intentando crear una función que tome un parámetro P, que es un objeto con las siguientes limitaciones:
Ppuede tener una propiedad de tipoTransformersque se define como{ [key in keyof T]?: (value: unknown) => unknown }Ppuede tener una propiedad de tipoComparersque se define como{ [key in keyof T]?: (obj: T, key: keyof T, value: T[key]) => boolean }- Si
Ptiene tantoTransformerscomoComparers, para las claves que aparecen en ambos, elvalorde esaclaveenComparersdebería basarse en el valor devuelto delTransformercorrespondiente.
Ejemplo :
type T1 = { a: string; b: number; c: Date }
type Transformers<T> = { [key in keyof T]?: (value: unknown) => unknown };
type Comparers<T> = { [key in keyof T]?: (obj: T, key: keyof T, value: T[key]) => boolean };
declare function MyFunc<T>(P: {
transformers: Transformers<T>,
comparers: Comparers<T>
}
MyFunc<T1>({
transformers: {
c: (value: number) => {
const from = new Date();
const to = new Date();
from.setMinutes(from.getMinutes() - value);
return { from, to };
}
},
comparers: {
a: (obj: T, value: string) => obj.a.startsWith(value),
c: (obj: T, value: { from: Date, to: Date }) => obj.c > value.from && obj[key] < value.to,
}
})
Esto, por supuesto, genera un error de TypeScript en la línea 19 porque el value para c en comparers no coincide con el tipo de T.c.
Mi intento más cercano de crear un tipo para esto hasta ahora:
type Transformer = (...args: unknown[]) => unknown;
type Transformers<T> = { [key in keyof T]?: Transformer };
type t1 = { a: number; b: string; c: Date };
type Comparers<T, TR = undefined> = {
[key in keyof T]?: (
obj: T,
value: key extends keyof TR
? TR[key] extends Transformer
? ReturnType<TR[key]>
: T[key]
: T[key]
) => boolean;
};
declare function Settings<T, TR extends Transformers<T>>(settings: {
transformers?: TR;
comparers: Comparers<T, TR>;
}): unknown;
const transformers = {
b: (value: unknown) => Number(value),
c: (value: unknown) => {
const from = new Date();
const to = new Date();
from.setMinutes(from.getMinutes() - Number(value));
return { from, to };
},
};
Settings<t1, typeof transformers>({
transformers,
comparers: {
a: (obj: t1, value: number) => {
const val = obj.a;
return val == value;
},
b: (obj: t1, value: number) => {
const val = obj.b;
return val.length >= value;
},
c: (obj: t1, value: { from: Date; to: Date }) => {
const val = obj.c;
return val > value.from && val < value.to;
},
},
});Esto funciona, pero requiere que cree un objeto para Transformers y pase su tipo a la función.
¿Hay alguna manera de hacer las comprobaciones que estoy buscando dentro del tipo de parámetro de la función, con solo un genérico T siendo requerido, y el resto infiriéndose a partir de las propiedades del parámetro?