Búsqueda de sitios web

typescript - ¿Cómo inferir el tipo de valor de un objeto dado una de sus claves?


Aquí hay un ejemplo sencillo donde estoy tratando de inferir el tipo del valor dado la clave proporcionada por el usuario.

// Function to update an object's value by key
export const updateValueByKey = <I>(
  obj: I,
  keyToUpdate: keyof I,
  newValue: I[keyof I] // Infers the type of all possible values, not the value of the given key
) => {
  obj[keyToUpdate] = newValue;
};

// Calling the function
updateValueByKey<{ id: number; name: string; isPrivate: boolean }>(
  {
    id: 123,
    name: "Some Note",
    isPrivate: false,
  },
  "id", // "id" | "name" | "isPrivate"
  "not a number" // number | string | boolean, should error because "id" requires a number
);

¿Cómo puedo asegurarme de que el nuevo valor proporcionado por el usuario coincida con el tipo del valor de la clave dada?

Respuesta #1

Si necesitas que updateValueByKey() haga un seguimiento del tipo literal del valor pasado como keyToUpdate, entonces la función necesita ser genérica en el tipo de ese parámetro:

export const updateValueByKey = <I, K extends keyof I>(
    obj: I,
    keyToUpdate: K,
    newValue: I[K] 
) => {
    obj[keyToUpdate] = newValue;
};

Y ahora obtienes el comportamiento que esperas (suponiendo que no necesites especificar manualmente I cuando lo llames, lo cual no necesitas, ya que pasas un valor de tipo I y el compilador puede inferirlo sin problema):

updateValueByKey(
    {
        id: 123,
        name: "Some Note",
        isPrivate: false,
    },
    "id",
    "not a number" // error! Argument of type 'string' is 
    // not assignable to parameter of type 'number'.
);

Enlace de Playground al código