JS / TS определяет, реализует ли объект JSON класс или интерфейс

#javascript #json #typescript

#javascript #json #typescript

Вопрос:

У меня есть объект JSON, проанализированный из строки.
Допустим, у этого объекта есть свойство с именем «Name», значением которого может быть простая строка или массив строк или даже объект, хранящий некоторую информацию о нем.

Во время выполнения я хочу иметь возможность находить тип значения (строка / массив / объект) и, если это объект, приводить его к правильному классу и запускать метод на основе этого.

У меня есть идея о том, как я собираюсь это сделать, но единственная проблема заключается в том, что я не уверен, как преобразовать объект в правильный тип.

Например, у меня есть класс, который принимает две строки, и другой класс, который принимает строку и число. Я хочу, чтобы программа увидела, какому из них он соответствует, а затем привела его к правильному классу.

Надеюсь, я выразился достаточно ясно, если потребуется дополнительная информация, пожалуйста, дайте мне знать.

Редактировать:

Вот решение, которое я использовал, чтобы заставить это работать (по крайней мере, для меня, это может быть не лучшим решением в каждом конкретном случае).

У меня есть абстрактный класс, называемый Parser

     export abstract class Parser {
    abstract parse(): string;

    clone(dataObject: object): Parser {
        if (this.validateData(dataObject) == false) return null;
        return this.cloneObject(dataObject);
    }
    protected abstract cloneObject(dataObject: object): Parser;

    protected validateData(data: object): boolean {
        const parserKeys = Object.keys(this);
        const dataKeys = Object.keys(data);

        for (let i = 0; i < parserKeys.length; i  ) {
            const parserKeyName = parserKeys[i];

            if (typeof this[parserKeyName] === "function") continue;
            const index = dataKeys.indexOf(parserKeyName);
            if (
                index == -1 ||
                typeof data[dataKeys[i]] !== typeof this[parserKeyName]
            )
                return false;
        }
        return true;
    }
}
  

У него есть метод validateData, который принимает объект (обычно объект JSON) и проверяет, что у него есть все переменные, имеющиеся в анализаторе.
Если данные действительны, он вызовет защищенный абстрактный метод, называемый cloneObject.

Вот простой класс под названием MinMaxParrser, который расширяет синтаксический анализатор

 import { Parser } from "./Parser";
import { randomNumber } from "./utils";

export class MinMaxParser extends Parser {
        min: 0;
        max: 1;
        constructor() {
            super();
            this.min = 0;
            this.max = 1;
        }
        parse(): string {
            return randomNumber(this.min, this.max).toString();
        }

        cloneObject(dataObject: object): MinMaxParser {
            let newParser = new MinMaxParser();
            newParser.min = dataObject["min"];
            newParser.max = dataObject["max"];

            return newParser;
        }
    }
  

Как вы можете видеть, у него есть метод cloneObject, который в основном возвращает экземпляр нового MinMaxParser

И, наконец, в основной программе у меня есть постоянный массив всех доступных анализаторов путем объявления объекта «sample»

 const availableParsers: Parser[] = [new MinMaxParser()];
  

Когда я хочу найти действительный анализатор, я использую этот метод

 private findValidParser(data: Object): Parser {
    let found = null;
    availableParsers.forEach(parser => {
        let clone = parser.clone(data);
        if (clone !== null) {
            found = clone;
        }
    });

    return found;
}
  

findValidParser возвращает мне синтаксический анализатор или null, я проверяю наличие null, и если это не null, я могу безопасно вызвать созданный мной метод parse ().

Комментарии:

1. Не могли бы вы добавить несколько примеров вместо того, чтобы так подробно описывать их словами, пожалуйста?

2. Прежде чем продолжить, пожалуйста, прочитайте о JSON .

3. Вы пробовали использовать typeof, возможно, с переключателем / регистром?

4. Object.prototype.toString.call(what_ever_object) возвращает «класс» объекта.

5. Это может быть просто неправильное использование терминов, но вы не можете привести литерал JSON (который вы получаете при разборе строки) к классу. Однако вы можете преобразовать его в интерфейс.

Ответ №1:

Используйте typeof и перегружайте функции, чтобы получить лучшие подсказки по типу:

 // narrow down types to get better typings
function parse(a: string, b: {}, c: string): Parser1;
//...

// implement generically
function parse(a: any, b: any, c: any): Parser {
 if(typeof a === "string" amp;amp; typeof b === "object" amp;amp; typeof c === "string") {
   return Parser1.parse(a, b, c);
 } /*...*/
}
  

Комментарии:

1. Спасибо, это вроде как то, что я искал. Но вместо того, чтобы делать много инструкций if, я, вероятно, создам функцию, которая посмотрит на класс и сравнит его для меня, а затем создаст экземпляр на основе этого (хотя это, вероятно, будет немного халтурно). Я опубликую решение с полным кодом позже сегодня, когда вернусь домой и закодирую его. И если я столкнусь с другой проблемой, я опубликую здесь. Спасибо.

Ответ №2:

Используйте следующее, чтобы проверить каждый

 let obj = {};
let str = '';
let num = 0;
let array = [];

console.log(Array.isArray(array))
console.log(typeof obj === 'object')
console.log(typeof str === 'string')
console.log(!isNaN(num))  

Комментарии:

1. Спасибо. Но с чем я действительно борюсь, так это с тем, является ли тип объектом, я хочу сделать его экземпляром класса на основе данных объекта.

2. сделать его экземпляром класса? вы хотите преобразовать объект в экземпляр класса? должно быть, это уже экземпляр, иначе вы не можете.