Встречался с различными парсерами JSON. Когда то было сложно сразу преобразовать дату в тот объект который хочется, иногда Enum жил своей жизнью. И вот не давно повстречал один Фреймворк для NodeJS. Речь пойдет про Ts.ED.
Вообщем ничего необычного, создаём класс прописываем свойства, и указываем тип для свойств. Этот класс соответственно указываем как ожидаемый тип в теле запроса.
public class User {
public middleName?: string;
}
Вроде понятно что ждём undefined
или строку. Но я не обозначаю тип null
для этого свойства. В запросе от клиента мне может прийти все что угодно в этом свойстве. Например null
, в этом случае Ts.ED возьмёт значение null
, да именно Js тип null
, и обернёт значение в кавычки. На эндпоинте я уже получу не null
а “null” и успешно запишу эту строку в БД. Фактически теперь у middleName будет строковое значение. Что я как-то совсем не ожидал.
Ладно окей думаю что сделаю union type для этого свойства:
public middleName?: string | null;
И теперь все норм работает, но есть маленький нюанс, я использую этот класс также для БД. Не на прямую конечно а через TypeORM. В этом случае эта библиотека выдаст исключение о не соответствии типа в БД (Github issue). Для TypeORM не достаточно указать union тип, ещё нужна мета информация. Ее можно передать через декоратор @Column
, который принимает опции в качестве параметра.
Хорошо, вообще я уже добавлял изначально следующие опции:
{ nullable: true }
Но этого не достаточно, погуглив какое то время я понял что если указывать такой union тип мне нужно явно обозначить тип для БД.
{ nullable: true, type: ‘character varying’ }
В итоге свойство будет выглядеть так:
@Column({ nullable: true, type: ‘character varying’ })
public middleName?: string | null;
Другой вариант решения возникшей ситуации это использовать Ts.ED декораторы. Для более старых версий, как у меня:
@Column({ nullable: true })
@Any(String)
public middleName?:string;
Тип String
в принципе и есть union type string | null
. С декоратором @Any
или в последних версиях с декоратором @Nullable
, Ts.ED больше не будет преобразовывать null в строку.
Еще одно дополнение про Ts.ED, по умолчанию он все пытается преобразовать в строку, например, как значение в параметрах.
@QueryParams(INCLUDE) include: boolean;
Опять же include=true
будет преобразовано в “true”
если явно не обозначить в декораторе тип Boolean
.
@QueryParams(INCLUDE, Boolean) include: boolean;