Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for Generic Types #125

Closed
jarredkenny opened this issue Jun 29, 2022 · 17 comments
Closed

Support for Generic Types #125

jarredkenny opened this issue Jun 29, 2022 · 17 comments
Assignees
Labels
documentation Improvements or additions to documentation good first issue Good for newcomers help wanted Extra attention is needed question Further information is requested
Projects

Comments

@jarredkenny
Copy link

I am very interested in Application Transformer, and converting TS types into json-schema/openapi.

I would like to be able to use TSON.application with a generic like so:

function toJsonSchema<T> {
  return TSON<T, "swagger",  "#/components/schemas">
}

It would be amazing if these generic references were unrolled at compile time.

However, today this throws Error: Error on TSON.application(): non-specified generic argument(s). and is not supported.

I am very new to typescript transformers so forgive my ignorance. Is this a limitation of transformers or something that just is not supported yet?

I've just come across this project that appears to resolve generic types via a transformer, https://github.com/Hookyns/tst-reflect

@samchon samchon added documentation Improvements or additions to documentation help wanted Extra attention is needed good first issue Good for newcomers question Further information is requested labels Jul 1, 2022
@samchon samchon added this to To do in v3.0 Update via automation Jul 1, 2022
@samchon
Copy link
Owner

samchon commented Jul 1, 2022

It looks interesting.

The reason why what I'd blocked non-generic-argumented function call is, typescript-json is generating optimized code by getting type info from the generic argument specification. I don't know exact principle of tst-reflect, how it specializes target type of non-generic-argumented function, but need study.

https://github.com/samchon/typescript-json/blob/3dfbeb097fdd6ea48e060844052aaa4d11274149/src/transformers/features/StringifyTransformer.ts#L14-L19

@samchon
Copy link
Owner

samchon commented Jul 2, 2022

I'll try this after #119.

If you can't wait 2 weeks later, solving the problem and sending PR would be good choice.

@samchon samchon added this to To do in v3.1 Update Jul 4, 2022
@KristjanTammekivi
Copy link
Contributor

Any chance to get this? My use-case is that I want to run the type tests in the same test suite as all the integration tests but this requires switching off transpile-only, which would make running the tests slower. So I thought I'd wrap TSON.assertType in a generic and try/catch/ignore if error matches transform is not available, and disable transpileOnly only in the CI.

I tried commenting out the if statements protecting against generics but the end result was Error: Error on TSON.assertType(): invalid type on $input, expect to be unknown

@samchon
Copy link
Owner

samchon commented Sep 12, 2022

Have not understood how to implement it yet.

If someone knows how to, please send a PR.

@cedrikaagaard
Copy link

Hi, typia is amazing!
I would also love to have support for generic types.

@samchon
Copy link
Owner

samchon commented Mar 7, 2023

This is out of my ability. Hope PR

@enote-kane
Copy link

+1 for this feature.

In our case, we want to provide a standard wrapper for internal projects for request payload validation using Express, which would look something like this:

import { Response } from "express";
import { IValidation, validate as typia_validate } from "typia";

export const validate = <T>(req: Request): T => {
  const validation: IValidation<T> = typia_validate<T>(req.body);
  if (!validation.success) {
    throw new MyCustomValidationError((validation as IValidation.IFailure).errors);
  }
  return (validation as IValidation.ISuccess<T>).data;
};

So here it just breaks because of the additional level of abstraction.

As I see it, we would need another transformer here that generates specific-type functions for the generically-typed one before the transformer of typia kicks in.

This could be an arbitrary-length chain of transformers or loop over the source code until all generically-typed function that call one of the functions exposed by typia are resolved.

Am I on the right track here? Anyone can provide some insights into transformers and what's possible and what isn't?

@samchon
Copy link
Owner

samchon commented Mar 20, 2023

@enote-kane About generic function, I can't even sure whether it would be possible or not.

In your case, I think using currying function would be the best choice:

import typia from "typia";
import { Response } from "express";

export const validate = 
    <T>(checker: (input: T) => typia.IValidation<T>) => 
    (req: Request) => {
        const result: typia.IValidation<T> = checker(req.body);
        if (!result.success)
            throw new MyCustomValidationError(result.errors);
        return result.data;
};

validate(typia.createValidate<MyDto>())(req);

@enote-kane
Copy link

@samchon Thanx for the hint, that works for me for the moment.

@samchon samchon closed this as not planned Won't fix, can't repro, duplicate, stale Apr 13, 2023
@kakasoo
Copy link
Sponsor Contributor

kakasoo commented May 23, 2023

I know this is a closed issue but I'm calling you here because I think it's dealing with the same topic.
First of all, is this an issue that has proved impossible?
If it is impossible, I think I should ask a question about the code below. I can't understand the two errors that occur in the two methods below.

type SomeGenericType<T extends string> = T extends '' ? never : string;
class TestClass<T extends string = '', P = SomeGenericType<T>> {
    /**
     * Error: Error on typia.random(): non-specified generic argument.
     */
    predict1() {
        return typia.random<P>(); // complie error
    }

    /**
     * non-compile error, but if I call this `predict` method, it occur error.
     *
     * for example, `TypeError: $pick(...) is not a function`
     */
    predict2() {
        return typia.random<SomeGenericType<T>>();
    }
}

new TestClass<'testStringType'>().predict2(); // error.

The annotations above each method describe the error. predict1 has an error at the time of compilation. I understand that this is because, like the error message, it is a generic type that cannot be specified at the time of compilation. The second predict2 would actually be the same type as P. However, there is an error at runtime after compiling.
I have a question that the error predict2 is a runtime error unlike predict1. Is this a solvable problem?

@samchon
Copy link
Owner

samchon commented May 23, 2023

@kakasoo Not possible at now because TypeScript compiler API can't specify it. But don't know how it would be in future.

@kakasoo
Copy link
Sponsor Contributor

kakasoo commented May 23, 2023

Thank you for your quick response. So what do you think about the above two methods, one getting an error at the time of compilation, and the other getting an error at the time of runtime? I think it's safer for both to have errors at the time of compilation, but is there no solution to this?

@samchon
Copy link
Owner

samchon commented May 23, 2023

No plan to do it, due to it would take a lot of time, but low expected effect.

However, it is okay to challenge by yourself.

@lewispham
Copy link

I think this is a serious issue as it forces us to create a validation (or protobuf) function for every single DTO. In other words, it makes typia a non-scalable library.

@samchon
Copy link
Owner

samchon commented Oct 13, 2023

@lewispham Then make something like nestia, no way to accomplish this suggestion

@lewispham
Copy link

@samchon How does nestia handle this then? If I'm not mistaken then it looks like typia does not support creating validation function with reflective types.

@samchon
Copy link
Owner

samchon commented Oct 16, 2023

When you want to get only type info, guide users to use typia.json.application() function.

Otherwise you want to use TypeScript compiler API directly, do something like this'

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
documentation Improvements or additions to documentation good first issue Good for newcomers help wanted Extra attention is needed question Further information is requested
Projects
No open projects
Development

No branches or pull requests

7 participants