Skip to content

Commit c910d20

Browse files
committed
[WIP] [Breaking] Drop Flow type support in favor of TypeScript
1 parent 66eb26a commit c910d20

File tree

5 files changed

+29
-62
lines changed

5 files changed

+29
-62
lines changed

__tests__/genTypeFlow.test.js renamed to __tests__/genType.test.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { getResourceTypeReference, getNewKeyTypeFromBatchKeySetType, getLoaderTypeKey } from '../src/genTypeFlow';
1+
import { getResourceTypeReference, getNewKeyTypeFromBatchKeySetType, getLoaderTypeKey } from '../src/genType';
22

33
it('getResourceTypeReference converts a resource path to a valid reference', () => {
44
expect(getResourceTypeReference(null, ['foo', 'bar', 'baz'])).toBe(

__tests__/implementation.test.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import { getConfig } from '../src/config';
99

1010
const BABEL_CONFIG = {
1111
presets: [
12-
'@babel/preset-flow',
12+
'@babel/preset-typescript',
1313
[
1414
'@babel/preset-env',
1515
{

src/codegen.ts

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import _ from 'lodash';
22
import prettier from 'prettier';
33
import { GlobalConfig, getResourcePaths } from './config';
4-
import { getLoaderType, getLoadersTypeMap, getResourceTypings } from './genTypeFlow';
4+
import { getLoaderType, getLoadersTypeMap, getResourceTypings } from './genType';
55
import getLoaderImplementation from './implementation';
66

77
function getLoaders(config: object, paths: Array<Array<string>>, current: Array<string>) {
@@ -46,8 +46,6 @@ export default function codegen(
4646
const { printResourceTypeImports, printResourcesType } = getResourceTypings(config);
4747

4848
const output = `
49-
// @flow strict-local
50-
5149
/**
5250
* !!! THIS FILE IS AUTO-GENERATED. CHANGES MAY BE OVERWRITTEN !!!
5351
*/
@@ -82,21 +80,22 @@ export default function codegen(
8280
* ===============================
8381
*/
8482
85-
// https://github.com/facebook/flow/issues/7709#issuecomment-530501257
86-
type ExtractArg = <Arg, Ret>([Arg => Ret]) => Arg;
87-
type ExtractPromisedReturnValue<A> = <R>((...A) => Promise<R>) => R;
83+
type PromisedReturnType<F extends (...args: any) => Promise<any>> =
84+
F extends (...args: any) => Promise<infer R> ? R : never;
85+
86+
type Values<T> = T[keyof T];
8887
89-
export type DataLoaderCodegenOptions = {|
88+
export type DataLoaderCodegenOptions = {
9089
errorHandler?: (
91-
resourcePath: $ReadOnlyArray<string>,
92-
// $FlowFixMe: We don't know what type the resource might throw, so we have to type error to "any" :(
90+
resourcePath: ReadonlyArray<string>,
91+
// We don't know what type the resource might throw, so we have to type error to "any" :(
9392
error: any,
9493
) => Promise<Error>,
95-
resourceMiddleware?: {|
96-
before?: <T>(resourcePath: $ReadOnlyArray<string>, resourceArgs: T) => Promise<T>,
97-
after?: <T>(resourcePath: $ReadOnlyArray<string>, response: T) => Promise<T>,
98-
|};
99-
|};
94+
resourceMiddleware?: {
95+
before?: <T>(resourcePath: ReadonlyArray<string>, resourceArgs: T) => Promise<T>,
96+
after?: <T>(resourcePath: ReadonlyArray<string>, response: T) => Promise<T>,
97+
};
98+
};
10099
101100
/**
102101
* ===============================

src/genTypeFlow.ts renamed to src/genType.ts

Lines changed: 12 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -13,39 +13,21 @@ const resourceReference = (resourcePath: ReadonlyArray<string>) => ['resources',
1313
* Get the reference to the type representing the resource function this resource
1414
*/
1515
export function getResourceTypeReference(resourceConfig: ResourceConfig, resourcePath: ReadonlyArray<string>) {
16-
function toPropertyTypePath(path: ReadonlyArray<string>): string {
17-
assert(path.length >= 1, 'expected resource path to be a not empty array');
18-
19-
if (path.length === 1) {
20-
return path[0];
21-
}
22-
23-
return `$PropertyType<${toPropertyTypePath(path.slice(0, -1))}, '${path.slice(-1)}'>`;
24-
}
25-
26-
return toPropertyTypePath(['ResourcesType', ...resourcePath]);
16+
return `ResourcesType${resourcePath.map(segment => `['${segment}']`).join()}`;
2717
}
2818

2919
function getResourceArg(resourceConfig: ResourceConfig, resourcePath: ReadonlyArray<string>) {
3020
// TODO: We assume that the resource accepts a single dict argument. Let's
3121
// make thie configurable to handle resources that use seperate arguments.
32-
return `\
33-
$Call<
34-
ExtractArg,
35-
[${getResourceTypeReference(resourceConfig, resourcePath)}]
36-
>`;
22+
return `Parameters<${getResourceTypeReference(resourceConfig, resourcePath)}>[0]`;
3723
}
3824

3925
/**
4026
* Extract the type T from a Set<T> resource (in this case a batchKey's resource)
4127
* using its `.has(T)`'s function paremeter type
4228
*/
4329
export function getNewKeyTypeFromBatchKeySetType(batchKey: string, resourceArgs: string) {
44-
return `\
45-
$Call<
46-
ExtractArg,
47-
[$PropertyType<$PropertyType<${resourceArgs}, '${batchKey}'>, 'has'>]
48-
>`;
30+
return `Parameters<${resourceArgs}['${batchKey}']['has']]>[0]`;
4931
}
5032

5133
export function getLoaderTypeKey(resourceConfig: ResourceConfig, resourcePath: ReadonlyArray<string>) {
@@ -55,8 +37,8 @@ export function getLoaderTypeKey(resourceConfig: ResourceConfig, resourcePath: R
5537

5638
if (resourceConfig.isBatchResource) {
5739
// Extract newKeyType from the batch key's Array's type
58-
// We add NonMaybeType before batch key element type to force the batch key to be required, regardless if the OpenAPI spec specifies it as being optional
59-
let newKeyType = `${resourceConfig.newKey}: $ElementType<$NonMaybeType<$PropertyType<${resourceArgs}, '${resourceConfig.batchKey}'>>, 0>`;
40+
// We add NonNullable before batch key element type to force the batch key to be required, regardless if the OpenAPI spec specifies it as being optional
41+
let newKeyType = `${resourceConfig.newKey}: NonNullable<${resourceArgs}['${resourceConfig.batchKey}']>[0]`;
6042

6143
if (resourceConfig.isBatchKeyASet) {
6244
/**
@@ -69,28 +51,14 @@ export function getLoaderTypeKey(resourceConfig: ResourceConfig, resourcePath: R
6951
)}`;
7052
}
7153

72-
return `{|
73-
...$Diff<${resourceArgs}, {
74-
${resourceConfig.batchKey}: $PropertyType<${resourceArgs}, '${resourceConfig.batchKey}'>
75-
}>,
76-
...{| ${newKeyType} |}
77-
|}`;
54+
return `Exclude<${resourceArgs}, '${resourceConfig.batchKey}'> & ${newKeyType}`;
7855
}
7956

8057
return resourceArgs;
8158
}
8259

8360
export function getLoaderTypeVal(resourceConfig: ResourceConfig, resourcePath: ReadonlyArray<string>) {
84-
// TODO: We assume that the resource accepts a single dict argument. Let's
85-
// make this configurable to handle resources that use seperate arguments.
86-
const resourceArgs = getResourceArg(resourceConfig, resourcePath);
87-
88-
// TODO: DRY up in codegen to something like RetVal<resource>
89-
let retVal = `\
90-
$Call<
91-
ExtractPromisedReturnValue<[${resourceArgs}]>,
92-
${getResourceTypeReference(resourceConfig, resourcePath)}
93-
>`;
61+
let retVal = `PromisedReturnType<${getResourceTypeReference(resourceConfig, resourcePath)}>`;
9462

9563
if (resourceConfig.isBatchResource) {
9664
/**
@@ -115,9 +83,9 @@ export function getLoaderTypeVal(resourceConfig: ResourceConfig, resourcePath: R
11583
* ```
11684
*/
11785
if (resourceConfig.nestedPath) {
118-
retVal = `$PropertyType<${retVal}, '${resourceConfig.nestedPath}'>`;
86+
retVal = `${retVal}['${resourceConfig.nestedPath}']`;
11987
}
120-
retVal = resourceConfig.isResponseDictionary ? `$Values<${retVal}>` : `$ElementType<${retVal}, 0>`;
88+
retVal = resourceConfig.isResponseDictionary ? `Values[${retVal}]` : `${retVal}[0]`;
12189
}
12290

12391
return retVal;
@@ -147,17 +115,17 @@ export function getLoadersTypeMap(
147115
const nextValues = _.uniq(paths.map((p) => p[0]));
148116

149117
const objectProperties: ReadonlyArray<string> = nextValues.map(
150-
(nextVal) =>
118+
(nextVal: any) =>
151119
`${nextVal}: ${getLoadersTypeMap(
152120
config,
153121
paths.filter((p) => p[0] === nextVal).map((p) => p.slice(1)),
154122
[...current, nextVal],
155123
)},`,
156124
);
157125

158-
return `$ReadOnly<{|
126+
return `Readonly<{
159127
${objectProperties.join('\n')}
160-
|}>`;
128+
}>`;
161129
}
162130

163131
export function getResourceTypings(

src/implementation.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { ResourceConfig, BatchResourceConfig, NonBatchResourceConfig } from './config';
22
import assert from './assert';
3-
import { getLoaderTypeKey, getLoaderTypeVal } from './genTypeFlow';
3+
import { getLoaderTypeKey, getLoaderTypeVal } from './genType';
44
import { errorPrefix } from './runtimeHelpers';
55

66
function getLoaderComment(resourceConfig: ResourceConfig, resourcePath: ReadonlyArray<string>): string {
@@ -32,7 +32,7 @@ function callResource(resourceConfig: ResourceConfig, resourcePath: ReadonlyArra
3232
// Uses an iife so the result variable is assignable at the callsite (for readability)
3333
return `
3434
(async _resourceArgs => {
35-
// Make a re-assignable variable so flow/eslint doesn't complain
35+
// Make a re-assignable variable so eslint doesn't complain
3636
let __resourceArgs = _resourceArgs;
3737
3838
if (options && options.resourceMiddleware && options.resourceMiddleware.before) {

0 commit comments

Comments
 (0)