• Remaps an object by applying field mappings while preserving original data.

    This function takes your original data object and a mapping configuration, then returns a new object that contains:

    • All original fields from the input data
    • Additional/overridden fields based on the mapping

    The mapping allows you to extract values using:

    • Simple property names: "fieldName"
    • Dot notation: "user.profile.name"
    • Array access: "items[0].id"
    • JSONPath expressions: "$.items[*].id"
    • Function extractors: (data) => data.customField

    Type Parameters

    • DataType extends Record<string, unknown>

    Parameters

    Returns DataType

    A new object with original fields plus mapped fields

    Basic remapping:

    const data = {
    name: "John",
    age: 30,
    email: "john@example.com",
    };

    const mapping: ObjectMapping<typeof data> = {
    userName: "name",
    userAge: "age",
    };

    const result = remapObject(data, mapping);
    // Result: {
    // name: "John",
    // age: 30,
    // email: "john@example.com",
    // userName: "John", // Added from mapping
    // userAge: 30, // Added from mapping
    // }

    Nested property extraction:

    const data = {
    user: {
    profile: {
    firstName: "John",
    lastName: "Doe",
    },
    email: "john@example.com",
    },
    };

    const mapping: ObjectMapping<typeof data> = {
    firstName: "user.profile.firstName",
    lastName: "user.profile.lastName",
    email: "user.email",
    };

    const result = remapObject(data, mapping);
    // Result includes original data plus:
    // {
    // firstName: "John",
    // lastName: "Doe",
    // email: "john@example.com",
    // }

    Array element access:

    const data = {
    items: [
    { id: 1, name: "Apple" },
    { id: 2, name: "Banana" },
    ],
    };

    const mapping: ObjectMapping<typeof data> = {
    firstItemId: "items[0].id",
    firstItemName: "items[0].name",
    };

    const result = remapObject(data, mapping);
    // Result includes:
    // {
    // firstItemId: 1,
    // firstItemName: "Apple",
    // }

    Function-based transformation:

    const data = {
    firstName: "John",
    lastName: "Doe",
    scores: [85, 92, 78],
    };

    const mapping: ObjectMapping<typeof data> = {
    fullName: (data) => `${data.firstName} ${data.lastName}`,
    averageScore: (data) =>
    data.scores.reduce((a, b) => a + b, 0) / data.scores.length,
    };

    const result = remapObject(data, mapping);
    // Result includes:
    // {
    // fullName: "John Doe",
    // averageScore: 85,
    // }

    Field override:

    const data = {
    name: "John",
    status: "inactive",
    };

    const mapping: ObjectMapping<typeof data> = {
    // Override existing field
    status: (data) => data.name === "John" ? "active" : "inactive",
    // Add new field
    displayName: (data) => `User: ${data.name}`,
    };

    const result = remapObject(data, mapping);
    // Result:
    // {
    // name: "John",
    // status: "active", // Overridden
    // displayName: "User: John", // Added
    // }

    Real-world evaluator usage:

    // Your data structure
    const example = {
    question: "What is AI?",
    context: "AI is artificial intelligence...",
    answer: "AI stands for artificial intelligence",
    };

    // Evaluator expects: { input, reference, output }
    const mapping: ObjectMapping<typeof example> = {
    input: "question",
    reference: "context",
    output: "answer",
    };

    const remapped = remapObject(example, mapping);
    // Now remapped has: { question, context, answer, input, reference, output }
    // The evaluator can access input, reference, and output fields