Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions src/__tests__/utils.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import {nullishToOptional} from '../utils';

describe('nullishToOptional', () => {
it('should return undefined for nullish values', () => {
expect(nullishToOptional(null)).toBeUndefined();
expect(nullishToOptional(undefined)).toBeUndefined();
});

it('should return the original value for non-nullish values', () => {
expect(nullishToOptional(0)).toBe(0);
expect(nullishToOptional('')).toBe('');
expect(nullishToOptional(false)).toBe(false);
expect(nullishToOptional('test')).toBe('test');
});
});
21 changes: 11 additions & 10 deletions src/offers/ticket-offer.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import {z} from 'zod';
import {nullishToOptional} from '../utils';

/**
* FlexDiscountStep in
* https://github.com/AtB-AS/sales/blob/main/sales-service/src/flexible.rs
*/
export const FlexDiscountStep = z.object({
expires: z.string().nullish(),
expires: z.string().nullish().transform(nullishToOptional),
discount: z.number(),
});
export type FlexDiscountStep = z.infer<typeof FlexDiscountStep>;
Expand All @@ -26,11 +27,11 @@ export type FlexDiscountLadder = z.infer<typeof FlexDiscountLadder>;
*/
export const SearchOfferPrice = z.object({
originalAmount: z.string(),
originalAmountFloat: z.number().nullish(),
originalAmountFloat: z.number().nullish().transform(nullishToOptional),
amount: z.string(),
amountFloat: z.number().nullish(),
amountFloat: z.number().nullish().transform(nullishToOptional),
currency: z.string(),
vatGroup: z.string().nullish(),
vatGroup: z.string().nullish().transform(nullishToOptional),
});
export type SearchOfferPrice = z.infer<typeof SearchOfferPrice>;

Expand All @@ -50,8 +51,8 @@ export enum OfferValidity {
*/
export const TicketRoute = z.object({
type: z.nativeEnum(OfferValidity),
from: z.string().nullish(),
to: z.string().nullish(),
from: z.string().nullish().transform(nullishToOptional),
to: z.string().nullish().transform(nullishToOptional),
});
export type TicketRoute = z.infer<typeof TicketRoute>;

Expand All @@ -64,12 +65,12 @@ export const TicketOffer = z.object({
travellerId: z.string(),
price: SearchOfferPrice,
fareProduct: z.string(),
validFrom: z.string().nullish(),
validTo: z.string().nullish(),
flexDiscountLadder: FlexDiscountLadder.nullish(),
validFrom: z.string().nullish().transform(nullishToOptional),
validTo: z.string().nullish().transform(nullishToOptional),
flexDiscountLadder: FlexDiscountLadder.nullish().transform(nullishToOptional),
route: TicketRoute,
shouldStartNow: z.boolean(),
available: z.number().nullish(),
available: z.number().nullish().transform(nullishToOptional),
});
export type TicketOffer = z.infer<typeof TicketOffer>;

Expand Down
15 changes: 15 additions & 0 deletions src/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
/**
* For use in cases where you want a value to be "optional" / `T | undefined`,
* but have to accept `null`.
*
* @example
* ```ts
* const Foo = z.string().nullish().transform(nullishToOptional)
* type Foo = z.infer<typeof Foo>; // `type Foo = string | undefined`
* ```
*/
export function nullishToOptional<T>(
value: T | null | undefined,
): T | undefined {
return value ?? undefined;
}