
“Se te ocurrió algo genial, Styopa”, me dijo un colega, dándose cuenta de la idea que se le había contado. Espero que sea cierto, aunque no diré que hay algo increíblemente innovador en lo que se discutirá más adelante, sin embargo, en mi opinión, este material sigue siendo de interés.
Hoy hablaremos sobre el uso de la introspección en el desarrollo de interfaces web, un poco de programación generalizada y reinventaremos la rueda en Typecript, que tiene un análogo similar en .NET.
¿Qué sabemos sobre la introspección?
, .
:
class Person {
height: number;
weight: number;
bloodPressure: string;
}
, , , .

, - .
const fields = ObjectFields.of(Person)
, , , . Object.keys
, keyof
. , , .
, . , , .
interface IObjectField<T extends object> {
readonly field: keyof T;
readonly type: string;
readonly value: any;
}
, , FieldInfo. :)
, Typescript — .NET. , . , C# .
, .
interface IConstructor<T> {
new(...args: any[]): T;
}
, , :
- , — .
-
IObjectField
- — .
Typescript.
class ObjectFields<T extends object> extends Array<IObjectField<T>> {
readonly [n: number]: IObjectField<T>;
constructor(type: IConstructor<T>) {
const instance: T = new type();
const fields: Array<IObjectField<T>> = (Object.keys(instance) as Array<keyof T>)
.map(x => {
const valueType = typeof instance[x];
let result: IObjectField<T> = {
field: x,
type: valueType === 'object'
? (instance[x] as unknown as object).constructor.name
: valueType,
value: instance[x]
}
return result;
});
super(...fields);
}
}
"" Person
.
const fields = new ObjectFields(Person);
console.log(fields);
, .

? . , Object.keys
, Javascript, , . — , , , - . "", - .
class Person {
height: number = 80;
weight: number = 188;
bloodPressure: string = '120-130 / 80-85';
}
— , .

.
class Material {
name = "wood";
}
class MyTableClass {
id = 1;
title = "";
isDeleted = false;
createdAt = new Date();
material = new Material();
}
.

?
Lo primero que me vino a la mente: las aplicaciones CRUD en react ahora se pueden escribir implementando componentes genéricos. Por ejemplo, necesita crear un formulario para insertarlo en una tabla. Por favor, nadie prohíbe hacer algo así.
interface ITypedFormProps<T extends object> {
type: IConstructor<T>;
}
function TypedForm<T extends object>(props: ITypedFormProps<T>) {
return (
<form>
{new ObjectFields(props.type).map(f => mapFieldToInput(f))}
</form>
);
}
Y luego usa este componente así.
<TypedForm type={Person} />
Bueno, la mesa en sí se puede hacer de acuerdo con el mismo principio.
Resumiendo
Me gustaría decir que la pieza resultó interesante, pero aún no está claro qué hacer con ella a continuación. Si estabas interesado o tienes alguna sugerencia, escribe en los comentarios, pero por ahora, ¡hasta pronto! ¡Gracias por la atención!