Type-safe json mapper
$ npm install --save @yamatomo/typed-json-mapper
or
$ yarn add @yamatomo/typed-json-mapper
import { TypedJsonMapper, map } from '@yamatomo/typed-json-mapper';
class Mapper extends TypedJsonMapper {
str = '';
num = Number.MIN_SAFE_INTEGER;
bool = false;
nil = null;
@map(String) arrayOfStrings: string[] = [];
}
// ------------------
const [mapper, err] = Mapper.map({
str: 'str', num: 123, bool: true, nil: null, array_of_strings: ['a', 'b']
});
/*
mapper => Mapper {
str: 'str',
num: 123,
bool: true,
nil: null,
arrayOfStrings: ['a', 'b']
}
*/
Use @map
decorator. (must)
class Mapper extends TypedJsonMapper {
@map(String) arrayOfString: string[] = [];
@map(Number) arrayOfNumber: number[] = [];
}
- custom type
- Implement a mapper class that inherit from
TypeJsonMapper
, and pass it to@map
decorator.
- Implement a mapper class that inherit from
- union type
- Implement a mapper functions, and pass it to
@map
decorator.
- Implement a mapper functions, and pass it to
import { TypedJsonMapper, map, Errors } from '@yamatomo/typed-json-mapper';
// you should implement mapper class
class CustomType extends TypedJsonMapper {
id = -1;
str = '';
}
// you should implement mapper function
const toNullableString = (data: unknown): [string | null, Errors] => {
const errors: Errors = typeof data === 'number' ? ['data type is number!'] : undefined;
return [data != null ? String(data) : null, errors];
}
class Mapper extends TypedJsonMapper {
// custom type
@map(CustomType) custom: CustomType = new CustomType();
// custom type + array
@map(CustomType) arrayOfCustom: CustomType[] = [];
// union type
@map(toNullableString) nullableStr: string | null = null;
// union type + array
@map(toNullableString) nullableStrings: (string | null)[] = [];
}
const toNullableString = (data: unknown): [string | null, Errors] => {
const errors: Errors = typeof data === 'number' ? ['data type is number!'] : undefined;
return [data != null ? String(data) : null, errors];
}
class Mapper extends TypedJsonMapper {
str = '';
num = -1
@map(toNullableString) nullableStr: string | null = 'default';
}
const [mapper, err] = Mapper.map({ num: 'string', nullable_str: 111 });
if (err) {
// something error handling
/*
err => [
'`Mapper.str` not exists mapping value.',
'`Mapper.num` type mismatch. expected-type: `number` actual: `"string"`',
'`Mapper.nullableStr` -> data type is number!'
]
*/
}
/*
mapper => Mapper {
str: '',
num: 0,
nullableStr: '111',
}
*/
Use @ignoreError
decorator.
class Mapper extends TypedJsonMapper {
@ignoreError str = '';
}
const [mapper, err] = Mapper.map({ str: 1111 });
/*
mapper => Mapper {
str: '1111',
}
*/
/*
err => undefined
*/
- disableTransformKeys (default: false)
- Disable snake-case to camel-case transform of keys when mapping.
- Can't use Non-null assertion operator.
- Can't use
undefined
type for property, usenull
instead
The typescript compiler can't detect mismatches between property types and mapper return types.
for example
class WrongTypeClass extends TypedJsonMapper {
@map(String) list: number[] = []; // <--- mapper return type = string, property type = number.
// A mismatch occurs, but no compile error occurs.
}
Check for such mismatches with this tool.
$ npx mapper-code-lint ./src/**/*.ts
or
$ yarn mapper-code-lint ./src/**/*.ts
MIT