¿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]);
