es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Tipo TypeScript para “Objeto con una clave llamada …”

Quiero crear una función como:

typescript
function sortByKey(items: T[], key: string): T[] {
return items.sort((a, b) => a[key] – b[key]);
}

Necesito que T[key] sea un number, pero no estoy seguro de cómo expresarlo.

Si supiera la clave de antemano, obviamente podría hacer {key: number}, pero eso no funciona aquí.

Intenté algo como sortByKey(items: {[k: K]: number}[], key: K), pero eso da el error "El tipo del parámetro de firma de índice no puede ser un tipo literal o un tipo genérico. Considere utilizar un tipo de objeto mapeado en su lugar.". Investigué sobre los tipos mapeados pero no parecen hacer lo que necesito. ¿Es algo como esto posible en TypeScript?

Tags:  ,

Answer

  1. Avatar for davy.ai

    Sí, es posible restringir el tipo de una clave dinámica en las funciones genéricas de TypeScript utilizando el operador keyof y tipos condicionales.

    Aquí hay una versión actualizada de la función sortByKey que solo acepta claves que se mapean a una propiedad de tipo number en el arreglo de elementos:

    function sortByKey<t, k="" extends="" keyof="" t="" &="" string="">(items: T[], key: K): T[] {
      return items.sort((a, b) => a[key] - b[key]);
    }
    

    Desglosemos las partes nuevas:

    • K extends keyof T & string restringe el tipo K a ser una clave del tipo T (es decir, uno de sus nombres de propiedad) y una cadena de texto (string).
    • El operador & combina varios tipos en un tipo de intersección. En este caso, estamos intersectando keyof T (el tipo de nombres de propiedad válidos en T) con string para crear un nuevo tipo que cumpla con ambos requisitos.
    • T[key] ahora está garantizado que sea de tipo number porque estamos restando a[key] de b[key] (lo cual solo funciona en números).

    Ahora puedes usar la función de la siguiente manera:

    interface Person {
      name: string;
      age: number;
      height: number;
    }
    
    const people: Person[] = [
      { name: 'Alice', age: 30, height: 1.5 },
      { name: 'Bob', age: 25, height: 1.7 },
      { name: 'Charlie', age: 40, height: 1.6 },
    ];
    
    sortByKey(people, 'age'); // ordena por edad
    sortByKey(people, 'height'); // ordena por altura
    sortByKey(people, 'name'); // Error: El argumento de tipo '"name"' no se puede asignar al parámetro de tipo '"age" | "height"'
    

    Ten en cuenta que la última línea produce un error de tipo porque 'name' no es una clave válida para ordenar objetos de tipo Person.</t,>

Comments are closed.