Файл определения машинописного текста для объектов json со строковыми атрибутами в качестве индикаторов типа.

Я изучаю создание файла определения машинописного текста для Plotly.js. Я просмотрел несколько примеров файлов определений в репозитории DefinitelyTyped. Один из вопросов, который приходит на ум, — это интерфейс для объекта Data. Объект данных представляет собой массив трассировок, как показано в plot-schema.

Рассмотрим этот пример объекта данных.

data = [
    {
         type: 'scatter',  
         x: [1, 2, 3],     
         y: [3, 1, 6],     
         marker: {         
             color: 'rgb(16, 32, 77)' 
         }
    },
    {
         type: 'bar',      
         x: [1, 2, 3],     
         y: [3, 1, 6],     
         name: 'bar chart example' 
    }
];

Типы трассировки, такие как «точечная» и «столбчатая», могут иметь разные атрибуты. Например, тип трассировки «круговая» имеет атрибут «направление».

Хотя я хотел бы определить отдельные интерфейсы для каждого типа трассировки с учетом общих атрибутов в интерфейсе более высокого уровня, я не вижу хорошего способа сделать это.

Самый интуитивный подход, о котором я могу думать, - это что-то вроде этого...

interface Trace {
    x: Array<any>;
    y: Array<any>;
}

interface BarTrace extends Trace {
   type: 'bar';
   // bar specific members
}

interface ScatterTrace extends Trace {
    type: 'scatter';
    // scatter specific members
}

Это недопустимый машинописный текст. Ожидается тип, а не строка 'bar' или 'scatter'.

Кто-нибудь знает о других библиотеках с аналогичной структурой, которые имеют определения машинописного текста, или о лучшем способе структурирования файла определения машинописного текста для этой структуры JSON?


person Bill Kidwell    schedule 18.12.2015    source источник
comment
Можно ли поместить type : 'path' | 'point' | 'polygon'; в родительский тип Trace? Это не привязывает дочерние типы к конкретным строкам, но предоставление интерфейсу фиксированного свойства экземпляра, которое не изменяется, в любом случае не имеет смысла в системе типизации — у типа есть имя (BarTrace, ScatterTrace), которое его идентифицирует. & это свойство типа делает то же самое.   -  person Stop Slandering Monica Cellio    schedule 13.06.2016
comment
Я попробую. Я не смотрел на это какое-то время. Спасибо за предложение.   -  person Bill Kidwell    schedule 16.06.2016


Ответы (1)


Я думаю, что ваш лучший вариант - продолжить, как вы, но определить type как строку. Что-то вроде следующего:

interface Trace {
    type: string;
    x: Array; 
    y: Array; 
}

interface BarTrace extends Trace {
   // bar specific members
}

interface ScatterTrace extends Trace {
    // scatter specific members
}

let data: Array<Trace> = [
    {
         type: 'scatter',  
         x: [1, 2, 3],     
         y: [3, 1, 6],     
         marker: {         
             color: 'rgb(16, 32, 77)' 
         }
    },
    {
         type: 'bar',      
         x: [1, 2, 3],     
         y: [3, 1, 6],     
         name: 'bar chart example' 
    }
];

Как только вы определите, является ли type «разбросом» или «полосой», вы можете привести переменную следующим образом.

data.forEach((item) => {
    if (item.type === 'scatter') {
        let trace: ScatterTrace = item;
        // ...
    } else {
        let trace: BarTrace = item;
        // ...
    }
});
person wjohnsto    schedule 18.12.2015
comment
Вы также можете использовать что-то вроде stackoverflow.com/a/22071913/227299 вместо строк - person Juan Mendes; 18.12.2015
comment
Спасибо @wjohnsto за быстрый ответ. Это похоже на направление, в котором я пойду, если у кого-то нет лучшего предложения. - person Bill Kidwell; 18.12.2015
comment
Спасибо @Juan-Mendes за предложение по струнам. - person Bill Kidwell; 18.12.2015