typescript - Filtrar un objeto basado en una interfaz
Todavía no he logrado encontrar una solución elegante para esto y siento que debería haber una, pero aún no tengo suficiente experiencia con Typescript para conocerla. Tengo una interfaz que define algunas claves permitidas en un objeto usado para la paginación
interface PaginationOptions {
page: number;
limit: number;
}
Mi objeto de entrada es una consulta HTTP ?page=1&limit=3&name=Foo que se traduce a
{
name: "Foo",
page: 1,
limit: 3,
}
Lo que quiero es poder hacer dos objetos a partir de eso, un objeto que contenga todos los valores de las claves definidas en la interfaz y un objeto que tenga cualquier otra clave. Por el momento estoy iterando a través del objeto entrante y separándolos manualmente, pero no puedo evitar pensar que hay una mejor manera. A continuación hay un ejemplo de los dos objetos que quiero hacer a partir de lo anterior.
{
page: 1,
limit: 3
}
y
{
name: "Foo"
}
Respuesta #1
La pregunta se reduce a esto: "¿Es posible implementar cierta lógica de JavaScript puramente basada en tipos de TypeScript?" Y la respuesta corta es "no", porque el código se compilará en JavaScript y la lógica aún necesita ser especificada de alguna manera.
Tomemos este código como ejemplo:
interface PaginationOptions {
page: number;
limit: number;
}
function makeTwoObjects<T extends PaginationOptions>(
input: T
): {
paginationOptions: PaginationOptions;
otherOptions: Omit<T, keyof PaginationOptions>;
} {
const { page, limit, ...otherOptions } = input;
return {
paginationOptions: { page, limit },
otherOptions,
};
}
La función está tipada, pero aún necesitamos extraer manualmente las propiedades que queremos del objeto. ¿Hay alguna manera de evitar esto?
Cuando el código finalmente se compile a JavaScript, terminaremos con una función de JavaScript que simplemente recibe un objeto y se supone que de alguna manera selecciona algunas propiedades de él.
Entonces, si no queremos desestructurar manualmente las propiedades, y si queremos evitar repetir la lista de props varias veces, todavía tenemos que especificarlas al menos una vez a la función de alguna otra manera. Como proporcionar otro argumento, por ejemplo, un arreglo con los nombres de las propiedades. Puedes usar lodash.pick para esto. Consulta esta respuesta para más información.
Esta es una forma de implementarlo en TypeScript:
function pick<T, K extends keyof T>(obj: T, ...keys: K[]): Pick<T, K> {
const ret = {} as Pick<T, K>;
keys.forEach((key) => {
ret[key] = obj[key];
});
return ret;
}
const input = {
page: 10,
limit: 20,
foo: "bar",
};
const result = pick(input, "page", "limit");
console.log(result);
// prints:
// {
// "page": 10,
// "limit": 20,
// };
