¿Cómo puedo escribir solo el valor y dejar que TypeScript infiera la clave de un objeto?
Tengo un objeto con cadenas como claves. Pero, no quiero que sea cadena. Quiero que las cadenas de las claves sean ese valor exacto del objeto. También tengo que escribir el valor de ese objeto para seguir ciertas reglas. Aquí hay un ejemplo,
type ObjectValueType = {
checked: boolean;
fields: Path<Camera>[];
};
type ObjectType = Record<string, ObjectValueType>;
const Object: ObjectType = {
camera_stream_endpoint: {
checked: false,
fields: ['camera_stream_endpoint'],
},
layout_image: {
checked: false,
fields: ['layout_image'],
},
};
En el objeto anterior, he creado un tipo de TypeScript ObjectType que tiene string como key y ObjectValueType como value. No quiero que key sea string. Quiero que el key sean las claves exactas del Object (camera_stream_endpoint o layout_image o rest). ¿Cómo infiero este key?
No quiero crear un tipo de unión de la clave del objeto porque ese objeto es un objeto extremadamente largo con muchas claves. Así que preferiría que TypeScript inferiera esa clave a partir del objeto creado.
Una cosa que intenté es usar la aserción as const de la siguiente manera
const Object = {
camera_stream_endpoint: {
checked: false,
fields: ['camera_stream_endpoint'],
},
layout_image: {
checked: false,
fields: ['layout_image'],
},
} as const;
Lo anterior logra el resultado deseado para las claves. Pero, ahora, puedo poner lo que quiera para el value. Por ejemplo, podría fácilmente estropear los fields que deberían seguir el tipo definido Path<Camera>. TypeScript no se quejará en absoluto por los valores incorrectos.
Quiero escribir las claves y valores del objeto. Las claves deberían inferirse a partir de la variable creada y los valores tendrán su propia definición de tipo. ¿Es posible?
Respuesta #1
Una solución que puedo ofrecer es inferir las claves de tu objeto const, definir el tipo que necesitas y luego asignar el objeto const a una variable del tipo deseado:
type ObjectValueType = {
checked: boolean;
fields: Path<Camera>[];
};
const ConstObject = {
camera_stream_endpoint: {
checked: false,
fields: ['camera_stream_endpoint'],
},
layout_image: {
checked: false,
fields: ['layout_image'],
},
};
type ObjectTypes = keyof typeof ConstObject;
export type CustomObject = { [key in ObjectTypes]: ObjectValueType };
export const Object: CustomObject = ConstObject;
Tenga en cuenta que debe eliminar la declaración const, ya que reducirá demasiado el parámetro fields para que el objeto sea asignable al tipo recién creado.
