Skip to content

Commit

Permalink
Merge pull request #122 from nobrainr/fix/strict-schema-class-typing
Browse files Browse the repository at this point in the history
Fix/strict schema class typing
  • Loading branch information
emyann authored Aug 31, 2019
2 parents 754c4b2 + 2a9fcd0 commit 883c2b8
Show file tree
Hide file tree
Showing 5 changed files with 46 additions and 13 deletions.
6 changes: 3 additions & 3 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@
"typedoc": "^0.15.0",
"typedoc-plugin-external-module-name": "^2.0.0",
"typedoc-plugin-internal-external": "^2.0.1",
"typescript": "^3.4.2",
"typescript": "3.5.3",
"webpack": "4.38.0",
"webpack-cli": "^3.3.0"
},
Expand Down
16 changes: 13 additions & 3 deletions src/morphism.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ function transformItems<T, TSchema extends Schema<T | {}>>(schema: TSchema, type
tree = new MorphismSchemaTree(schema);
}

function mapper(source: any) {
const mapper: Mapper<TSchema> = (source: any) => {
if (!source) {
return source;
}
Expand All @@ -96,7 +96,7 @@ function transformItems<T, TSchema extends Schema<T | {}>>(schema: TSchema, type
return transformValuesFromObject(object, tree, [object], jsObject);
}
}
}
};

return mapper;
}
Expand Down Expand Up @@ -148,7 +148,17 @@ function morphism<TSchema extends Schema, TDestination>(
type: Constructable<TDestination>
): Mapper<TSchema, TDestination>; // morphism({}, null, T) => mapper(S) => T

function morphism<TSchema extends Schema, Target>(schema: TSchema, items: SourceFromSchema<TSchema>, type: Constructable<Target>): Target; // morphism({}, {}, T) => T
function morphism<
TSchema = Schema<DestinationFromSchema<Schema>, SourceFromSchema<Schema>>,
Target = never,
Source extends SourceFromSchema<TSchema> = SourceFromSchema<TSchema>
>(schema: TSchema, items: Source, type: Constructable<Target>): Target; // morphism({}, {}, T) => T

function morphism<
TSchema = Schema<DestinationFromSchema<Schema>, SourceFromSchema<Schema>>,
Target = never,
Source extends SourceFromSchema<TSchema> = SourceFromSchema<TSchema>
>(schema: TSchema, items: Source[], type: Constructable<Target>): Target[]; // morphism({}, [], T) => T[]

function morphism<Target, Source, TSchema extends Schema<Target, Source>>(
schema: TSchema,
Expand Down
12 changes: 6 additions & 6 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,17 +37,17 @@ export type StrictSchema<Target = any, Source = any> = {
| ActionString<Source>
| ActionFunction<Target, Source, Target[destinationProperty]>
| ActionAggregator<Source>
| ActionSelector<Source, Target[destinationProperty]>
| StrictSchema<Target[destinationProperty], Source>
| ActionSelector<Source, Target>
| StrictSchema<Target[destinationProperty], Source>;
} & { [SCHEMA_OPTIONS_SYMBOL]?: SchemaOptions<Target> };
export type Schema<Target = any, Source = any> = {
/** `destinationProperty` is the name of the property of the target object you want to produce */
[destinationProperty in keyof Target]?:
| ActionString<Source>
| ActionFunction<Target, Source, Target[destinationProperty]>
| ActionAggregator<Source>
| ActionSelector<Source, Target[destinationProperty]>
| Schema<Target[destinationProperty], Source>
| ActionSelector<Source, Target>
| Schema<Target[destinationProperty], Source>;
} & { [SCHEMA_OPTIONS_SYMBOL]?: SchemaOptions<Target | any> };

export type Actions<Target, Source> = ActionFunction<Target, Source> | ActionAggregator | ActionString<Target> | ActionSelector<Source>;
Expand Down Expand Up @@ -172,6 +172,6 @@ export type DestinationFromSchema<T> = T extends StrictSchema<infer U> | Schema<
export type ResultItem<TSchema extends Schema> = DestinationFromSchema<TSchema>;

export interface Mapper<TSchema extends Schema | StrictSchema, TResult = ResultItem<TSchema>> {
(data: SourceFromSchema<TSchema>[]): TResult[];
(data: SourceFromSchema<TSchema>): TResult;
(data?: SourceFromSchema<TSchema>[] | null): TResult[];
(data?: SourceFromSchema<TSchema> | null): TResult;
}
23 changes: 23 additions & 0 deletions src/typescript.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,29 @@ describe('Typescript', () => {
morphism<StrictSchema<D1, S1>>({ a: ({ _a }) => _a.toString() });
morphism<StrictSchema<D1, S1>>({ a: ({ _a }) => _a.toString() });
});

it('shoud infer result type from source when a class is provided', () => {
class Source {
constructor(public id: number, public ugly_field: string) {}
}

class Destination {
constructor(public id: number, public field: string) {}
}

const source = [new Source(1, 'abc'), new Source(1, 'def')];

const schema: StrictSchema<Destination, Source> = {
id: 'id',
field: 'ugly_field'
};
const expected = [new Destination(1, 'abc'), new Destination(1, 'def')];

const result = morphism(schema, source, Destination);
result.forEach((item, idx) => {
expect(item).toEqual(expected[idx]);
});
});
});

describe('Morphism Function Type Checking', () => {
Expand Down

0 comments on commit 883c2b8

Please sign in to comment.