Búsqueda de sitios web

¿Cómo especificar el tipo de retorno de lodash.groupBy con el Enum de Typescript?


¿Cómo especificar el tipo de retorno de lodash.groupBy con el Enum de TypeScript?

enum Gender {
  Male = 'male',
  Female = 'female'
}

interface Person {
  name: string;
  gender: string;
}

const people: Person[] = [
  { name: 'Mary', gender: 'female' },
  { name: 'Jerry', gender: 'male' },
  { name: 'Joe', gender: 'male' }
]

type PeopleGroupedByGender = {
  [key in keyof typeof Gender]: Person[]
}

// HERE: I can't get it to work so that the return type is PeopleGroupedByGender, typescript compiler complains:
// Type 'Dictionary<Person[]>' is missing the following properties from type 'PeopleGroupedByGender': Male, Female ts(2739)


const groupPeopleByGender = (people: Person[]): PeopleGroupedByGender => {
  return _.groupBy(people, (person: Person) => {
    return person.gender === Gender.Male ? Gender.Male : Gender.Female
  })
}

http://www.typescriptlang.org/play/index. html#código/ KYOwrgtgBA4qAmwBOUDeAoKUCyBDANsFALxQDkEBwZANJlAGLCWEnkBmzVZ6AvuugCWIAC7J2uAMZEACsgDOAexBp6IXBGAAuKPJFJhAcwDc9QwmQ69BkCb4DJyvVAAOwRS8I65SJSADaALps-vSoUOqaOmR4SACetFDmIIhI0Zws1FC8dFjhkdrkAFLI8YnJqdGZZNm5aBEahWRFitQ0SRZp5NXZ6IECInFuUHIehDBIimBu8ABCcXApyPyGwYWP4A1sBxUMJQm3GK7FCDboewnYHeCspB9ugA9PdQABIAogBKrzoAklCSuCAyCIOsDBMCRIooAB3RRIda6SEiAAWuHBSKISGAIjASBUJyIgnkI3cnmAEymM3mi1S7Xx8kkBhcwMcEBcgkIKBZnlwwnkWgeTwAKkMiGQACKCSQiQTKXDxAA8Pj8QQAfDVCVAIIT5EZjuioOxFPh8IoobqXJM3EhpcAiexJtB8eRRqTydNgHMFp0yDo8IR2kxMsd5AAKABMAHYAMwATgAlAJ0I4QM5DJNpi7CFTOmwQ6dSVdfDdAnGrmMyenKV6lihiCrVFhMdjcVAAPoAOjTFPmeZJ-qgvaLIELfjjJHrqywUCbOJUVr8nZzxGX5xr7b9RAA-KvUuuqFAdNTkO3A1R6LwE7wgA

Respuesta #1

Tú sabes que el resultado de groupBy() va a ser un objeto con claves por los strings en Gender, pero las definiciones de tipo para Lodash especifican que devuelve un Dictionary<T> que es un objeto con claves por strings y valores de tipo T.

Tienes tres opciones: No especificar el tipo de retorno de groupPeopleByGender(), y vivir con las claves de tipo cadena, convirtiendo el resultado de groupBy() a PeopleGroupedByGender ya que sabes que eso será lo que obtendrás, o sobrescribir las definiciones de tipo de Lodash.

Solución de fundición

const groupPeopleByGender = (people: Person[]) => 
  <PeopleGroupedByGender>_.groupBy(people, (person: Person) => 
    person.gender === Gender.Male ? Gender.Male : Gender.Female);

Solución de Modificación de Definición de Tipo

Basé lo siguiente en lo que ya está en collection.d.ts y common.d.ts. Utiliza la funcionalidad de fusión de declaraciones de TypeScript para actualizar el módulo lodash con una nueva implementación de groupBy() con un resultado correctamente tipado.

Aviso: No entiendo la filosofía detrás del diseño de su repositorio de tipos, así que podría haber pasado por alto algún matiz. Usa esto como guía para tu solución final.

// lodash-extended.ts
import * as _ from 'lodash';
import { List, ValueIterateeCustom, LoDashStatic } from 'lodash';

declare module 'lodash' {
  type StringishDictionary<V, K extends string> = {
    [index in K]: V;
  }
  interface LoDashStatic  {
    groupBy<T, K extends string>(
        collection: List<T> | null | undefined,
        iteratee?: ValueIterateeCustom<T, K>
    ): StringishDictionary<T[], K>;
  }
}

index.ts

import * as _ from 'lodash';

enum Gender { Male = 'male', Female = 'female' }
interface Person { name: string; gender: string; }
const people: Person[] = [ /** Persons added here. **/ ]

const groupPeopleByGender = (people: Person[]) => 
   _.groupBy(people, x => (x.gender == Gender.Male) ? Gender.Male : Gender.Female);

// Groups will be keyed by Gender with values of Person[].
const groups = groupPeopleByGender(people);
// Below is valid syntax and will display the first Male.
console.log(groups[Gender.Male][0]);

StackBlitz

Artículos relacionados