Saltar al contenido

¿Cómo hacer una conversión de tipos en tiempo de ejecución en TypeScript?

Nuestro equipo especializado pasados muchos días de trabajo y recopilación de de datos, obtuvimos los datos necesarios, deseamos que te sea útil para tu proyecto.

Solución:

El prototipo de la clase se puede afectar dinámicamente al objeto:

function cast(obj: any, cl:  new(...args): T ): T 
  obj.__proto__ = cl.prototype;
  return obj;


var john = cast(/* somejson */, Person);

Consulte la documentación de __proto__ aquí.

Eche un vistazo al JavaScript compilado y verá que la aserción de tipo (casting) desaparece porque es solo para compilar. En este momento le está diciendo al compilador que el somejson el objeto es de tipo Person. El compilador te cree, pero en este caso no es así. true.

Entonces, este problema es un problema de JavaScript en tiempo de ejecución.

El objetivo principal para que esto funcione es decirle de alguna manera a JavaScript cuál es la relación entre las clases. Asi que…

  1. Encuentre una manera de describir la relación entre las clases.
  2. Cree algo para asignar automáticamente el json a las clases en función de estos datos de relación.

Hay muchas maneras de resolverlo, pero voy a ofrecer un ejemplo de la parte superior de mi cabeza. Esto debería ayudar a describir lo que hay que hacer.

Digamos que tenemos esta clase:

class Person 
    name: string;
    child: Person;

    public giveName() 
        return this.name;
    

Y estos datos json:

 
    name: 'John', 
    child: 
        name: 'Sarah',
        child: 
            name: 'Jacob'
        
    

Para mapear esto automáticamente para que sean instancias de Person, necesitamos decirle al JavaScript cómo se relacionan los tipos. No podemos usar la información de tipo de TypeScript porque la perderemos una vez compilada. Una forma de hacer esto es tener un static propiedad en el tipo que describe esto. Por ejemplo:

class Person 
    static relationships = 
        child: Person
    ;

    name: string;
    child: Person;

    public giveName() 
        return this.name;
    

Luego, aquí hay un ejemplo de una función reutilizable que maneja la creación de objetos para nosotros en función de estos datos de relación:

function createInstanceFromJson(objType:  new(): T; , json: any)  ;

    for (const prop in json) 
        if (json.hasOwnProperty(prop)) 
            if (newObj[prop] == null) 
                if (relationships[prop] == null) 
                    newObj[prop] = json[prop];
                
                else 
                    newObj[prop] = createInstanceFromJson(relationships[prop], json[prop]);
                
            
            else 
                console.warn(`Property $prop not set because it already existed on the object.`);
            
        
    

    return newObj;

Ahora funcionará el siguiente código:

const someJson =  
        name: 'John', 
        child: 
            name: 'Sarah',
            child: 
                name: 'Jacob'
            
        
    ;
const person = createInstanceFromJson(Person, someJson);

console.log(person.giveName());             // John
console.log(person.child.giveName());       // Sarah
console.log(person.child.child.giveName()); // Jacob

Patio de juegos

Idealmente, la mejor manera sería usar algo que realmente lea el código TypeScript y cree un objeto que mantenga la relación entre las clases. De esa manera, no necesitamos mantener manualmente las relaciones y preocuparnos por los cambios de código. Por ejemplo, en este momento refactorizar el código es un poco arriesgado con esta configuración. No estoy seguro de que exista algo así en este momento, pero definitivamente es posible.

Solución alternativa

Me acabo de dar cuenta de que ya respondí una pregunta similar con una solución ligeramente diferente (aunque eso no implica datos anidados). Puedes leerlo aquí para obtener más ideas:

JSON a instancia de clase TypeScript?

Puede usar Object.assign, por ejemplo:

var somejson =  'name' : 'Ann' ;
var ann = Object.assign(new Person, somejson);

console.log(ann.name);        // 'Ann'
console.log(ann.giveName());  // 'Ann'

Pero si tiene clases anidadas, debe asignar el lanzamiento del objeto y asignar para cada elemento.

Si conservas alguna indecisión o forma de beneficiar nuestro post te proponemos ejecutar una reseña y con placer lo interpretaremos.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)


Tags : /

Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *