typescript - Tubos tipados en Angular
Muchos pipes personalizados con los que me topo estos días están tipados como any, pero como yo, y mi equipo, nos gustaría aprovechar las bondades de IntelliSense, he estado experimentando con tipar algunos pipes, sin éxito.
Espié en la tubería incorporada de Angular llamada slice que tiene una definición que se ve así: transform<T>(value: ReadonlyArray<T>, start: number, end?: number): Array<T>;.
Basándome en eso, hice un ejemplo simple para combinar dos arreglos:
import { Pipe, PipeTransform } from '@angular/core';
@Pipe({
name: 'concat'
})
export class ConcatPipe implements PipeTransform {
public transform<T>(
arr1: ReadonlyArray<T>,
arr2: ReadonlyArray<T>,
): Array<T> {
return [...arr1, ...arr2];
}
}
Problema
Mi IDE (VS Code) reporta el siguiente error cuando intento usar el pipe y acceder a una propiedad en mi plantilla HTML: Identifier 'fileStatus' is not defined. 'T' does not contain such a member. "fileStatus" es la propiedad a la que estoy intentando acceder en los miembros del arreglo en este caso particular.
Pregunta
¿No es esta la manera correcta de escribir un pipe? ¿No es posible esto (como parece ser con el pipe slice incorporado)?
Actualizar
Como señaló "Antoniossss" en su respuesta, la implementación real solo declara las variantes tipadas y aún utiliza any en la implementación real. He actualizado mi código como se muestra a continuación, pero IntelliSense todavía no se proporciona, y el error sigue presente.
import { Pipe, PipeTransform } from '@angular/core';
@Pipe({
name: 'concat'
})
export class ConcatPipe implements PipeTransform {
public transform<T>(arr1: ReadonlyArray<T>, arr2: ReadonlyArray<T>): Array<T>;
public transform(
arr1: any[],
arr2: any[],
): any[] {
return [...arr1, ...arr2];
}
}
Respuesta #1
Si revisas el código real de SlicePipe, verás que las variantes tipadas solo se declaran para sugerencias, pero no están implementadas
https://github.com/angular/angular/blob/d1ea1f4c7f3358b730b0d94e65b00bc28cae279c/packages/common/src/pipes/slice_pipe.ts
transform<T>(value: ReadonlyArray<T>, start: number, end?: number): Array<T>;
transform(value: string, start: number, end?: number): string;
transform(value: null, start: number, end?: number): null;
transform(value: undefined, start: number, end?: number): undefined;
transform(value: any, start: number, end?: number): any {
if (value == null) return value;
if (!this.supports(value)) {
throw invalidPipeArgumentError(SlicePipe, value);
}
return value.slice(start, end);
}
private supports(obj: any): boolean {
return typeof obj === 'string' || Array.isArray(obj);
}
y toda la magia está ocurriendo en la variante no tipada tomada de la interfaz PipeTransform - transform(value: any, start: number, end?: number).
Tendrás que hacer lo mismo
