Estoy tratando de verificar si una variable es una instancia de Socket de ZeroMQ en tiempo de ejecución. En JavaScript, esto funciona:

doCheck(input) {
    if (input instanceof zmq.Socket) {
        console.log("Is a socket.");
    }
    else {
        console.log("Is not a socket.");
    }
}

Sin embargo, en TypeScript, se queja de zmq.Socket, diciendo que no se ha exportado desde el archivo de definición de tipo. Ese archivo define Socket como una interfaz, por lo que no es el tipo correcto para verificar si se trata de una instancia. ¿Cómo puedo hacer que funcione la verificación instanceof?

1
Jez 31 oct. 2017 a las 15:27

3 respuestas

La mejor respuesta

Si zmq.Socket se exporta como una interfaz, no puede usar instanceof en este tipo. Podría perder el tiempo en la implementación para ver qué clase se instancia realmente, pero sería desordenado y poco confiable.

Una opción sería verificar que existan varios métodos que espera que existan en el objeto y ponerlo en una función de protección de tipo para que pueda cambiarlo más adelante si es necesario:

import * as zmq from 'zmq'

function isSocket( sock: any ) : sock is zmq.Socket {
    var castSock = sock as zmq.Socket;
    // If it has all the methods it's probably a zmq.Socket
    return castSock.getsocketopt !== undefined
        && castSock.connect      !== undefined
        && castSock.disconnect   !== undefined
        && castSock.close        !== undefined;
}

function doCheck(input) {
    if (isSocket(input) ) {
        input.close() // input is of a type zmq.Socket
        console.log( "Is a ZeroMQ Socket instance." );
    }
    else {
        console.log( "Is not a ZeroMQ Socket instance." );
    }
}

Editar:

Si el código instanceof funciona en JS simple, eso significa que la definición es incorrecta y Socket debería ser una clase. Puede corregirlo y enviarlo al proyecto, pero mientras tanto puede agregar el siguiente código en el archivo que usa instanceof:

declare module 'zmq' {
    export class Socket {}
}

function doCheck(input : zmq.Socket | string) {
    if (input instanceof zmq.Socket) {
        input.close() // input is of type zmq.Socket
         console.log( "Is a ZeroMQ Socket instance." );
    }
    else {
        console.log( "Is not a ZeroMQ Socket instance." );
    }
}
2
user3666197 31 oct. 2017 a las 17:10

Además de probar algunos análisis de inferencia de tipos, re-casting et al,
recomendaría

construir sobre una prueba bastante explícita:

Supongamos que ya hay un razonamiento detrás de la decisión de un diseñador de cuál es la versión mínima de API admitida, y luego, cada instancia de ZeroMQ Socket debe proporcionar una respuesta sin excepciones a todos y cada uno Solicitud documentada por API:

try {
    var aLinger = inputUnderTest.getsockopt( zmq.LINGER     ); // ZMQ_LINGER
    var aCpuAfi = inputUnderTest.getsockopt( zmq.AFFINITY   ); // ZMQ_AFFINITY
    var aMaxMSZ = inputUnderTest.getsockopt( zmq.MAXMSGSIZE ); // ZMQ_MAXMSGSIZE
    var aRecvBF = inputUnderTest.getsockopt( zmq.RCVBUF     ); // ZMQ_RCVBUF
    var aRecvWM = inputUnderTest.getsockopt( zmq.RCVHWM     ); // ZMQ_RCVHWM
    var aRecvTO = inputUnderTest.getsockopt( zmq.RCVTIMEO   ); // ZMQ_RCVTIMEO
    var aRecvMO = inputUnderTest.getsockopt( zmq.RCVMORE    ); // ZMQ_RCVMORE
    var aSendBF = inputUnderTest.getsockopt( zmq.SNDBUF     ); // ZMQ_SNDBUF
    var aSendWM = inputUnderTest.getsockopt( zmq.SNDHWM     ); // ZMQ_SNDBUF
    var aSendTO = inputUnderTest.getsockopt( zmq.SNDTIMEO   ); // ZMQ_SNDTIMEO
    var aFDESCR = inputUnderTest.getsockopt( zmq.FD         ); // ZMQ_FD

    console.log( 'Seems to match a ZeroMQ Socket instance.' );

}
catch (e){

    console.log( 'Was not a ZeroMQ Socket instance.' );

    }
}

Cualquier falta de respuesta de una manera libre de excepciones significa:
o bien, una inputUnderTest no es una instancia de ZeroMQ Socket Q.E.D.
o
una versión de API ZeroMQ o una implementación de enlace / envoltura específica del idioma se ha deslizado y de alguna manera se ha cambiado silenciosamente detrás de nuestros cuellos: o)

Cualquiera de los dos ayuda a decidir sobre nuestros próximos pasos.

0
user3666197 31 oct. 2017 a las 17:39

No puede verificar la interfaz instanceof, ya que solo es de tipo conocido por Typecript. Después de la compilación, se eliminan todas las interfaces y tipos, por lo que en el código JavaScript ejecutado no hay tipos / interfaces en los que pueda confiar. Si desea marcar instanceof necesita proporcionar algún tipo de función constructora.

Puede consultar el fragmento del área de juegos que muestra cómo funciona aquí. Tenga en cuenta que no hay interfaz en la versión compilada de código.

Puede consultar la documentación oficial para obtener una explicación más descriptiva aquí.

1
Kacper Wiszczuk 31 oct. 2017 a las 12:40