Skip to content

Commit

Permalink
fix(type-compiler): support ReceiveType in arrow function with body e…
Browse files Browse the repository at this point in the history
…xpression

This makes sure the following works correctly:

```typescript
(type?: ReceiveType) => (v: any) => {
    type = resolveReceiveType(type);
    // ...
};
```
  • Loading branch information
marcj committed May 8, 2024
1 parent 0136971 commit e1ce203
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 4 deletions.
16 changes: 13 additions & 3 deletions packages/type-compiler/src/compiler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
* You should have received a copy of the MIT License along with this program.
*/

import type {
import ts, {
__String,
ArrayTypeNode,
ArrowFunction,
Expand Down Expand Up @@ -43,6 +43,8 @@ import type {
InferTypeNode,
InterfaceDeclaration,
IntersectionTypeNode,
isBlock,
isExpression,
LiteralTypeNode,
MappedTypeNode,
MethodDeclaration,
Expand Down Expand Up @@ -72,7 +74,6 @@ import type {
TypeReferenceNode,
UnionTypeNode,
} from 'typescript';
import ts from 'typescript';

import {
ensureImportIsEmitted,
Expand Down Expand Up @@ -1105,7 +1106,16 @@ export class ReflectionTransformer implements CustomTransformer {
this.f.createToken(ts.SyntaxKind.EqualsToken),
this.f.createIdentifier('undefined'),
));
const body = node.body ? this.f.updateBlock(node.body as Block, [reset, ...(node.body as Block).statements]) : undefined;

// convert expression into statements array
let body = node.body && isBlock(node.body) ? node.body : undefined;
let bodyStatements: Statement[] = node.body && isBlock(node.body) ? [...node.body.statements] : [];
if (node.body) {
if (isExpression(node.body)) {
bodyStatements = [this.f.createReturnStatement(node.body)];
}
body = this.f.updateBlock(node.body as Block, [reset, ...bodyStatements]);
}

if (isArrowFunction(node)) {
return this.f.updateArrowFunction(node, node.modifiers, node.typeParameters, node.parameters, node.type, node.equalsGreaterThanToken, body as ConciseBody) as T;
Expand Down
15 changes: 15 additions & 0 deletions packages/type-compiler/tests/transpile.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -536,3 +536,18 @@ test('resolve type ref2', () => {
console.log(res.app);
expect(res.app).toContain(`() => Guest, 'Guest'`);
});

test('ReceiveType arrow function', () => {
const res = transpile({
'app': `
export const typeValidation = <T>(type?: ReceiveType<T>): ValidatorFn => (control: AbstractControl) => {
type = resolveReceiveType(type);
const errors = validate<T>(control.value)
console.log(errors)
return errors.length ? {validation: errors[0]} : null
}
`
});
console.log(res.app);
expect(res.app).toContain(`exports.typeValidation.Ω = undefined; return __assignType((control) =>`);
});
13 changes: 12 additions & 1 deletion packages/type/tests/receive-type.spec.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { expect, test } from '@jest/globals';
import { ReceiveType, resolveReceiveType, typeOf } from '../src/reflection/reflection.js';
import { ReflectionKind, Type } from '../src/reflection/type.js';
import { ReflectionOp } from '@deepkit/type-spec';
import { validates } from '../src/validator.js';

test('typeOf', () => {
const type = typeOf<string>();
Expand Down Expand Up @@ -97,3 +97,14 @@ test('class constructor multiple', () => {
expect(aString.type1).toMatchObject({ kind: ReflectionKind.string });
expect(aString.type2).toMatchObject({ kind: ReflectionKind.number });
});

test('function with ReceiveType return expression', () => {
const typeValidation = <T>(type?: ReceiveType<T>) => (value: any) => {
type = resolveReceiveType(type);
return validates(value, type);
}

const validateString = typeValidation<string>();
expect(validateString('hello')).toBe(true);
expect(validateString(2)).toBe(false);
});

0 comments on commit e1ce203

Please sign in to comment.