samchon / typia

Super-fast/easy runtime validators and serializers via transformation
https://typia.io/
MIT License
4.62k stars 159 forks source link

Reflection? #732

Closed mindplay-dk closed 1 year ago

mindplay-dk commented 1 year ago

Question

Just wondering, do you have any plans to broad the scope of this library to more general-purpose reflection features?

Such as, iterating over the properties of a (possibly abstract) type, checking the compatibility of a specified type against a specified argument, and so on? (features that would enable us to create a dependency injection container, a router that automatically injects dependencies for the function, and so forth.)

(or perhaps a separate library?)

You clearly understand this stuff really well, and there is not much happening in that space. 😊

(apologies if this has already been asked - I didn't find the answer in issues, or in the docs.)

samchon commented 1 year ago

No plan to support the Reflection, because typia is planned to support interface type.

As you know, interface type never can utilize the Reflection.

mindplay-dk commented 1 year ago

As you know, interface type never can utilize the Reflection.

Well, not without a runtime - but the same is true for other features in typia, and there are other projects attempting to do that.

Most languages that do support reflection, such as PHP and C#, do allow reflection of interface types.

Of course, this is only relevant if you want to actually support reflection. :-)

samchon commented 1 year ago

If possible to support reflection on interface type, I'll do it. Do you know how to do it?

mindplay-dk commented 1 year ago

If you mean how to implement it? No.

If you mean, how should the feature work? Probably something like getType<T>(), which would return some sort of reflection model - you could look at the C# or PHP models for reference.

Anyhow, this is probably a big feature. πŸ˜…

Refzlund commented 1 year ago

Working backwards can help with understanding the need and bridging the idea. So an example of reflection, as I interpret it from @mindplay-dk:

What

interface Person {
    name: string
    /** @minimum 3 */
    age: number
    nested: {
        /** @custom A custom attribute to access */
        value: boolean
    }
}

const personInterface = getType<Person>()
/*
    personInterface: TypeOf<Person> = {
        'name': {
            type: 'string',
        },
        'age': {
            type: 'number',
            attributes: { // Record<string, string> as comments are impossible to type.
                '@minimum': '3'
            }
        },
        'nested': {
            type: 'object',
            properties: {
                'value': {
                    type: 'boolean',
                    attributes: {
                        '@custom': 'A custom attribute to access'
                    }
                }
            }
        }
    }
*/

const validatePerson = createValidate(personInterface) // infers Person from TypeOf<infer P>

Why

When working with other systems such as databases, or automatically rendering components on a frontend, being able to iterate properties and knowing their "options"; in this case the comment-attributes becomes quite central.

So this reflection allows us to communicate an interface to modules that doesn't do AOT like Typia (so all other modules basically).


I'm personally rooting for an implementation like this.

Is this what you had in mind @mindplay-dk?


P.S. I don't think Reflection capable of executing this. Following Typia's existing API, it could just be a part of the AOT compilation.

To clarify; Reflection is code executed at runtime, which accesses and manipulates objects using Runtime-driven code. Whereas AOT compilation is executed at TS compile time that generates JavaScript-native code, such as s simple object as seen in the example above.

E.g. Reflection would iterate an interface, while AOT would iterate keys on an object. From my knowledge Reflection is really only applicable on TypeScript classes, and not so much on interfaces/types.

mindplay-dk commented 1 year ago

Yeah, something like that. :-)

From my knowledge Reflection is really only applicable on TypeScript classes, and not so much on interfaces/types.

Classes and interfaces, but also functions and constructors - so we could build things like IOC containers and routers.

Refzlund commented 1 year ago

@mindplay-dk If Reflection is inspecting/manipulating objects and data-structures in runtime, then, no, you can't really use "reflection" on an interface, as the interface is removed after TS compiles to JS - and that was just my point. That means, the technique that allows for "reflection", is AOT - but the result has nothing to do with an interface, but rather, an object. So you're using reflection at compile time, which ... is not reflection at all (?), but AOT. If @samchon took your comment on using "Reflection" literal, then I understand the confusion.

Anyways, I just wanted to share that there's https://github.com/nullcc/ts-interface-keys-transformer. It is however not maintained. Issue #12 fixes an issue with a type and supports comment arguments. So we can be inspired by that in regards to this issue.

For now I'm hoping @samchon doesn't mind adding this utility-transformer to our wishlist🀞

samchon commented 1 year ago

As typia (and nestia) is targetting to interface type, and reflect cannot be used for such interface type, I reject this suggestion.

Instead, I'll accept those things, and you may satisfy them.

It may come into typia in v5.1 version, after protobuf and gql supporting.

Thanks for suggestion, and sorry for rejection.

mindplay-dk commented 1 year ago

@samchone That's quite alright! I was only wondering if reflection was in the "neighborhood" of what you were doing already - it sounds like it's not, so that feature probably doesn't belong here. It's a big, complex feature in itself, anyhow. πŸ™‚

@Refzlund not really following anything you're saying here? reflection has nothing to do with a language being AOT or JIT or interpreted - for example, C# is AOT, PHP is JIT/interpreted, and both support reflection of interfaces. I understand that TS is different from PHP and C#, in that it performs type erasure - maybe that's what you meant? But that doesn't preclude reflection. You can still generate a reflection of the source code model, at compile-time, which you can then consume at run-time. I am currently testing this library, which is attempting to implement exactly that approach. πŸ™‚

AlexRMU commented 3 months ago

What about https://github.com/samchon/typia/issues/878#issuecomment-1896149792