angular - ¿Cómo puedo escribir un typeguard que reconozca si algo es un Type<T>?
Tengo una definición de tipo que permite varias formas de proporcionar un objeto:
type ObjSource<T> = InjectionToken<T> | Type<T> | ((context: IContext) => (T | Promise<T>)) | Promise<T> | T;Ahí, IContext es una interfaz propia que proporciona alguna información de contexto sobre (una parte de) mi aplicación.
Para evaluar correctamente todo esto, necesito averiguar qué objeto fuente se suministró realmente. Estoy intentando hacerlo con funciones de protección de tipo personalizadas. Empecemos:
- Si el valor es del tipo
InjectionToken<T>oType<T>, simplemente me gustaría introducirlo en la funcióninjectde Angular, permitiendo así que la inyección de dependencias de Angular lo gestione. - Si el valor es del tipo
((context: IContext) => (T | Promise<T>)), me gustaría ejecutar esa función y pasar el resultado aPromise.resolve. - De lo contrario, es decir, si el valor es del tipo
Promise<T>oT, me gustaría pasarlo aPromise.resolve.
Ahora, ¿cómo puedo distinguir estos casos?
Creo que puedo reconocer un
InjectionToken<T>por el hecho de ser una instancia de la claseInjectionToken:function isInjectionToken<T>(x: ObjSource<T>): x is InjectionToken<T> { return x instanceof InjectionToken; }- Sé casi nada sobre
T. Podría ser capaz de restringirlo aT extends object. En ese caso, distingo(context: IContext) => (T | Promise<T>)dePromise<T> | Tpor el hecho de quetypeofdevuelvefunctionpara el primero, pero no para el segundo.
Pero ¿cómo distingo Type<T> de (context: IContext) => (T | Promise<T>)?
El Type<T> de Angular se define como:
class Type<T> extends Function {
constructor(...args: any[]): T
}
Usando una pequeña aplicación de Angular, he probado varias implementaciones para isType<T>(x: ProviderToken<T>): x es Type<T> aquí:
export class App {
public doClick() {
const a = isType(function blah() {
return true;
});
const b = isType(new InjectionToken<string>('xyz'));
const c = isType(App);
alert(`${a} ${b} ${c}`);
}
}
Hasta ahora, sin embargo, no he podido encontrar los criterios correctos para verificar:
x instanceof Typedevuelvetruepara el tercero, pero también para el primer caso.typeof x === 'function'(sin sorpresa) también devuelvetruepara el primer y el tercer caso.typeof x === 'function' && Object.prototype.hasOwnProperty.call(x, 'constructor'), por otro lado, devuelvefalseen todos los casos.