Skip to content
This repository has been archived by the owner on Feb 20, 2020. It is now read-only.

Commit

Permalink
Add create-various-curried-function-types
Browse files Browse the repository at this point in the history
  • Loading branch information
ikatyang committed May 10, 2017
1 parent c7eb5f3 commit 14422da
Show file tree
Hide file tree
Showing 10 changed files with 450 additions and 22 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ All changes to this project will be documented in this file.
> - 🏠 [Internal]
> - 💅 [Polish]
## Unreleased
- advanced
- add `create_various_curried_function_types()`: for functional-programming types with deep generics and multi version

## v1.2.1 (2017-05-09)

#### 🐛 Bug Fix
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,17 @@ exports[`should return correctly with placeholder 1`] = `
(v1: T1): R;
}
interface CurriedFunction2<T1, T2, R> {
(v1: T1, v2: T2): R;
(_1: PH, v2: T2): CurriedFunction1<T1, R>;
(v1: T1, v2: T2): R;
(v1: T1): CurriedFunction1<T2, R>;
}
interface CurriedFunction3<T1, T2, T3, R> {
(v1: T1, v2: T2, v3: T3): R;
(v1: T1, _2: PH, v3: T3): CurriedFunction1<T2, R>;
(_1: PH, v2: T2, v3: T3): CurriedFunction1<T1, R>;
(_1: PH, _2: PH, v3: T3): CurriedFunction2<T1, T2, R>;
(v1: T1, v2: T2): CurriedFunction1<T3, R>;
(v1: T1, v2: T2, v3: T3): R;
(_1: PH, v2: T2): CurriedFunction2<T1, T3, R>;
(v1: T1, v2: T2): CurriedFunction1<T3, R>;
(v1: T1): CurriedFunction2<T2, T3, R>;
}"
`;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,30 +3,30 @@
exports[`should return correctly with placeholder 1`] = `
"type adjust = adjust_000;
type adjust_000 = {
<T, U>(fn: (v: T) => U, index: number, array: T[]): adjust_111<T, U>;
<T, U>(fn: (v: T) => U, _index: PH, array: T[]): adjust_101<T, U>;
<T>(_fn: PH, index: number, array: T[]): adjust_011<T>;
<T>(_fn: PH, _index: PH, array: T[]): adjust_001<T>;
<T, U>(fn: (v: T) => U, index: number): adjust_110<T, U>;
<T, U>(fn: (v: T) => U, index: number, array: T[]): adjust_111<T, U>;
(_fn: PH, index: number): adjust_010;
<T, U>(fn: (v: T) => U, index: number): adjust_110<T, U>;
<T, U>(fn: (v: T) => U): adjust_100<T, U>;
};
type adjust_001<T> = {
<U>(fn: (v: T) => U, index: number): adjust_111<T, U>;
(_fn: PH, index: number): adjust_011<T>;
<U>(fn: (v: T) => U, index: number): adjust_111<T, U>;
<U>(fn: (v: T) => U): adjust_101<T, U>;
};
type adjust_010 = {
<T, U>(fn: (v: T) => U, array: T[]): adjust_111<T, U>;
<T>(_fn: PH, array: T[]): adjust_011<T>;
<T, U>(fn: (v: T) => U, array: T[]): adjust_111<T, U>;
<T, U>(fn: (v: T) => U): adjust_110<T, U>;
};
type adjust_011<T> = {
<U>(fn: (v: T) => U): adjust_111<T, U>;
};
type adjust_100<T, U> = {
(index: number, array: T[]): adjust_111<T, U>;
(_index: PH, array: T[]): adjust_101<T, U>;
(index: number, array: T[]): adjust_111<T, U>;
(index: number): adjust_110<T, U>;
};
type adjust_101<T, U> = {
Expand All @@ -41,32 +41,32 @@ type adjust_111<T, U> = (T | U)[];"
exports[`should return correctly with placeholder and selectable 1`] = `
"type adjust = adjust_000;
type adjust_000 = {
<T, U>(fn: (v: T) => U, index: number, array: T[]): adjust_111<T, U>;
<T, U>(fn: (v: T) => U, _index: PH, array: T[]): adjust_101<T, U>;
<T>(_fn: PH, index: number, array: T[]): adjust_011<T>;
<T>(_fn: PH, _index: PH, array: T[]): adjust_001<T>;
<T, U>(fn: (v: T) => U, index: number): adjust_110<T, U>;
<T, U>(fn: (v: T) => U, index: number, array: T[]): adjust_111<T, U>;
(_fn: PH, index: number): adjust_010;
<X extends \\"111\\">(): <T, U>(fn: (v: T) => U, index: number, array: T[]) => adjust_111<T, U>;
<T, U>(fn: (v: T) => U, index: number): adjust_110<T, U>;
<X extends \\"1\\">(): <T, U>(fn: (v: T) => U) => adjust_100<T, U>;
<X extends \\"101\\">(): <T, U>(fn: (v: T) => U, _index: PH, array: T[]) => adjust_101<T, U>;
<X extends \\"011\\">(): <T>(_fn: PH, index: number, array: T[]) => adjust_011<T>;
<X extends \\"001\\">(): <T>(_fn: PH, _index: PH, array: T[]) => adjust_001<T>;
<X extends \\"11\\">(): <T, U>(fn: (v: T) => U, index: number) => adjust_110<T, U>;
<X extends \\"01\\">(): (_fn: PH, index: number) => adjust_010;
<X extends \\"1\\">(): <T, U>(fn: (v: T) => U) => adjust_100<T, U>;
<X extends \\"111\\">(): <T, U>(fn: (v: T) => U, index: number, array: T[]) => adjust_111<T, U>;
<T, U>(fn: (v: T) => U): adjust_100<T, U>;
};
type adjust_001<T> = {
<U>(fn: (v: T) => U, index: number): adjust_111<T, U>;
(_fn: PH, index: number): adjust_011<T>;
<U>(fn: (v: T) => U, index: number): adjust_111<T, U>;
<X extends \\"11\\">(): <U>(fn: (v: T) => U, index: number) => adjust_111<T, U>;
<X extends \\"01\\">(): (_fn: PH, index: number) => adjust_011<T>;
<X extends \\"1\\">(): <U>(fn: (v: T) => U) => adjust_101<T, U>;
<U>(fn: (v: T) => U): adjust_101<T, U>;
};
type adjust_010 = {
<T, U>(fn: (v: T) => U, array: T[]): adjust_111<T, U>;
<T>(_fn: PH, array: T[]): adjust_011<T>;
<T, U>(fn: (v: T) => U, array: T[]): adjust_111<T, U>;
<X extends \\"11\\">(): <T, U>(fn: (v: T) => U, array: T[]) => adjust_111<T, U>;
<X extends \\"01\\">(): <T>(_fn: PH, array: T[]) => adjust_011<T>;
<X extends \\"1\\">(): <T, U>(fn: (v: T) => U) => adjust_110<T, U>;
Expand All @@ -76,8 +76,8 @@ type adjust_011<T> = {
<U>(fn: (v: T) => U): adjust_111<T, U>;
};
type adjust_100<T, U> = {
(index: number, array: T[]): adjust_111<T, U>;
(_index: PH, array: T[]): adjust_101<T, U>;
(index: number, array: T[]): adjust_111<T, U>;
<X extends \\"11\\">(): (index: number, array: T[]) => adjust_111<T, U>;
<X extends \\"01\\">(): (_index: PH, array: T[]) => adjust_101<T, U>;
<X extends \\"1\\">(): (index: number) => adjust_110<T, U>;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`should return correctly 1`] = `
"type map = map_00;
type map_00 = {
<T>(_fn: PH, mappable: Mappable<T>): map_mappable_01<T>;
<T>(_fn: PH, array: T[]): map_array_01<T>;
<T, U>(fn: (v: T) => U, array: T[]): map_array_11<T, U>;
<T, U>(fn: (v: T) => U, mappable: Mappable<T>): map_mappable_11<T, U>;
<K extends \\"array\\", X extends \\"01\\">(): <T>(_fn: PH, array: T[]) => map_array_01<T>;
<K extends \\"mappable\\">(): map_mappable_00;
<X extends \\"1\\">(): <T, U>(fn: (v: T) => U) => map_10<T, U>;
<K extends \\"array\\">(): map_array_00;
<K extends \\"array\\", X extends \\"11\\">(): <T, U>(fn: (v: T) => U, array: T[]) => map_array_11<T, U>;
<K extends \\"mappable\\", X extends \\"11\\">(): <T, U>(fn: (v: T) => U, mappable: Mappable<T>) => map_mappable_11<T, U>;
<K extends \\"mappable\\", X extends \\"01\\">(): <T>(_fn: PH, mappable: Mappable<T>) => map_mappable_01<T>;
<T, U>(fn: (v: T) => U): map_10<T, U>;
};
type map_10 = {
(array: T[]): map_array_11<T, U>;
<K extends \\"array\\">(): (array: T[]) => map_array_11<T, U>;
<K extends \\"mappable\\">(): (mappable: Mappable<T>) => map_mappable_11<T, U>;
(mappable: Mappable<T>): map_mappable_11<T, U>;
};
type map_array_00 = {
<T>(_fn: PH, array: T[]): map_array_01<T>;
<T, U>(fn: (v: T) => U, array: T[]): map_array_11<T, U>;
<X extends \\"11\\">(): <T, U>(fn: (v: T) => U, array: T[]) => map_array_11<T, U>;
<X extends \\"01\\">(): <T>(_fn: PH, array: T[]) => map_array_01<T>;
<X extends \\"1\\">(): <T, U>(fn: (v: T) => U) => map_array_10<T, U>;
<T, U>(fn: (v: T) => U): map_array_10<T, U>;
};
type map_array_01<T> = {
<U>(fn: (v: T) => U): map_array_11<T, U>;
};
type map_array_10<T, U> = {
(array: T[]): map_array_11<T, U>;
};
type map_array_11<T, U> = U[];
type map_mappable_00 = {
<T>(_fn: PH, mappable: Mappable<T>): map_mappable_01<T>;
<T, U>(fn: (v: T) => U, mappable: Mappable<T>): map_mappable_11<T, U>;
<X extends \\"11\\">(): <T, U>(fn: (v: T) => U, mappable: Mappable<T>) => map_mappable_11<T, U>;
<X extends \\"01\\">(): <T>(_fn: PH, mappable: Mappable<T>) => map_mappable_01<T>;
<X extends \\"1\\">(): <T, U>(fn: (v: T) => U) => map_mappable_10<T, U>;
<T, U>(fn: (v: T) => U): map_mappable_10<T, U>;
};
type map_mappable_01<T> = {
<U>(fn: (v: T) => U): map_mappable_11<T, U>;
};
type map_mappable_10<T, U> = {
(mappable: Mappable<T>): map_mappable_11<T, U>;
};
type map_mappable_11<T, U> = Mappable<U>;"
`;
55 changes: 55 additions & 0 deletions src/advanced/__tests__/create-various-curried-function-types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
jest.disableAutomock();

import {TypeDeclaration} from '../../elements/declarations/type-declaration';
import {Document} from '../../elements/document';
import {Parameter} from '../../elements/parameter';
import {ArrayType} from '../../elements/types/array-type';
import {BasicType} from '../../elements/types/basic-type';
import {FunctionType} from '../../elements/types/function-type';
import {GenericType} from '../../elements/types/generic-type';
import {TypedType} from '../../elements/types/typed-type';
import {create_various_curried_function_types} from '../create-various-curried-function-types';

const name = 'map';
const generic_T = new GenericType({name: 'T'});
const generic_U = new GenericType({name: 'U'});
const parameter_fn = new Parameter({
name: 'fn',
type: new FunctionType({
parameters: [new Parameter({name: 'v', type: generic_T})],
return: generic_U,
}),
});

const function_type_array = new FunctionType({
generics: [generic_T, generic_U],
parameters: [
parameter_fn,
new Parameter({name: 'array', type: new ArrayType({owned: generic_T})}),
],
return: new ArrayType({owned: generic_U}),
});

const mappable = new TypeDeclaration({name: 'Mappable'});
const function_type_mappable = new FunctionType({
generics: [generic_T, generic_U],
parameters: [
parameter_fn,
new Parameter({name: 'mappable', type: new TypedType({owned: mappable, generics: [generic_T]})}),
],
return: new TypedType({owned: mappable, generics: [generic_U]}),
});

it('should return correctly', () => {
const types = create_various_curried_function_types({
name,
types: {
array: function_type_array,
mappable: function_type_mappable,
},
selectable: true,
placeholder: new BasicType({name: 'PH'}),
});
const document = new Document({children: types});
expect(document.emit()).toMatchSnapshot();
});
11 changes: 10 additions & 1 deletion src/advanced/create-curried-function-interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,10 +106,19 @@ export const create_curried_function_interfaces = ({
}
})([], parameters.slice(0, index + 1));

const parameters_index_of = (sort_parameters: Parameter[]): number =>
sort_parameters.findIndex((parameter: Parameter) => (placeholder === null)
? false
: parameter.has(placeholder, true));

an_interface.parameters.members.sort((member1: ObjectMember, member2: ObjectMember) => {
const function_type_1: FunctionType = member1.parameters.owned.parameters.type;
const function_type_2: FunctionType = member2.parameters.owned.parameters.type;
return function_type_2.parameters.parameters.length - function_type_1.parameters.parameters.length;
const parameters_1 = function_type_1.parameters.parameters;
const parameters_2 = function_type_2.parameters.parameters;
return (parameters_1.length !== parameters_2.length)
? parameters_2.length - parameters_1.length
: parameters_index_of(parameters_2) - parameters_index_of(parameters_1);
});
});

Expand Down
23 changes: 17 additions & 6 deletions src/advanced/create-curried-function-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {TypedType} from '../elements/types/typed-type';
import {get_default_placeholder_name_generator} from './utils/get-default-placeholder-name-generator';
import {get_default_select_type_generator} from './utils/get-default-select-type-generator';
import {get_default_type_name_generator} from './utils/get-default-type-name-generator';
import {sort_object_members} from './utils/sort-object-members';

export interface ICreateCurriedFunctionTypesRequiredParameters {
name: string;
Expand All @@ -21,6 +22,7 @@ export interface ICreateCurriedFunctionTypesOptionalParameters {
placeholder: Type | null;
selectable: boolean;
select_generic_name: string;
is_various: boolean;
generate_select_type(type: FunctionType): Type;
generate_type_name(index: number): string;
generate_placeholder_name(parameter_name: string): string;
Expand Down Expand Up @@ -53,6 +55,7 @@ export const create_curried_function_types = ({
type,
placeholder = null,
selectable = false,
is_various = false,
select_generic_name = 'X',
generate_select_type = get_default_select_type_generator(placeholder),
generate_type_name = get_default_type_name_generator(name, type),
Expand Down Expand Up @@ -193,12 +196,20 @@ export const create_curried_function_types = ({
}
});

curried_type_declarations.unshift(new TypeDeclaration({
name,
type: new TypedType({
owned: curried_type_declarations[0],
}),
}));
if (!is_various) {
curried_type_declarations.forEach((type_declaration: TypeDeclaration): void => {
const target_type = type_declaration.parameters.type;
if (target_type instanceof ObjectType) {
sort_object_members(target_type.parameters.members, placeholder);
}
});
curried_type_declarations.unshift(new TypeDeclaration({
name,
type: new TypedType({
owned: curried_type_declarations[0],
}),
}));
}

return curried_type_declarations;
};
Loading

0 comments on commit 14422da

Please sign in to comment.