Предположим, у меня есть записи пользователя в моем PureScript код с следующего типа:Создание PureScript записей из несовместимых объектов JavaScript
{ id :: Number
, username :: String
, email :: Maybe String
, isActive :: Boolean
}
CommonJS модуль выводится из кода PureScript. Экспортированные функции, связанные с пользователем, будут вызываться из внешнего кода JavaScript.
В коде JavaScript "пользователь" может быть представлен в виде:
var alice = {id: 123, username: 'alice', email: '[email protected]', isActive: true};
email
может быть null
:
var alice = {id: 123, username: 'alice', email: null, isActive: true};
email
могут быть опущены:
var alice = {id: 123, username: 'alice', isActive: true};
isActive
могут быть опущены, и в этом случае это как SUMED true
:
var alice = {id: 123, username: 'alice'};
id
, к сожалению, иногда числовая строка:
var alice = {id: '123', username: 'alice'};
Пяти JavaScript представления выше эквивалентны и должны производить эквивалентное PureScript записи.
Как мне написать функцию, которая принимает объект JavaScript и возвращает запись пользователя? Он использует значение по умолчанию для необязательного поля null/omitted, принуждает строку id
к числу и бросает, если отсутствует требуемое поле или если значение имеет неправильный тип.
Два подхода, которые я вижу, - это использование FFI в модуле PureScript или определение функции преобразования во внешнем JavaScript-коде. Последнее кажется волосатым:
function convert(user) {
var rec = {};
if (user.email == null) {
rec.email = PS.Data_Maybe.Nothing.value;
} else if (typeof user.email == 'string') {
rec.email = PS.Data_Maybe.Just.create(user.email);
} else {
throw new TypeError('"email" must be a string or null');
}
// ...
}
Я не уверен, как будет работать версия FFI. Я еще не работал с эффектами.
Прошу прощения, что этот вопрос не очень ясен. У меня еще недостаточно понимания, чтобы точно знать, что я хочу знать.
[примеры/Objects.purs] (https://github.com/purescript/purescript-foreign/blob/v0.3.0/examples/Objects.purs) кажется ближе всего к что я пытаюсь сделать. Как я могу изменить этот пример, чтобы позволить 'x' быть либо числом, либо числовой строкой? – davidchambers
Одним из способов было бы создать такой тип, как 'data SoN = S String | N Number' , а затем записать 'IsForeign' экземпляр для типа' SoN' с помощью '' <|> оператора объединить две альтернативы: 'чтения F = S <$> ReadString F <|> N <$> readNumber f' –