Prunoideae / ProbeJS

Supercharging your modpack experience.
GNU General Public License v3.0
47 stars 15 forks source link

types of param/return in a lambda looks suspicious #92

Closed ZZZank closed 3 months ago

ZZZank commented 3 months ago

lambdas seems to be receiving a "solid type" param and returns a duck type, which does not match the behaviour of regular functions and methods(recive "duck" and return "solid")

E.g. These codes:

ProbeEvents.modifyClass((event) => {
    const ingr = $Types.typeMaybeGeneric($Ingredient)
    const lam = $Types.lambda().param("someArg", ingr).returnType(ingr).build()
    event.modify($TypingModificationEventJS, (file) => {
        file.addCode(
            $Statements.method("exampleMethod")
            .param("lamArg", lam)
            .returnType(lam)
            .build()
        )
    })
})

will produce a result like this:

function exampleMethod(
    lamArg: (someArg: $Ingredient) => $Ingredient$$Type
): (someArg: $Ingredient) => $Ingredient$$Type

My expectation is that at least the second lambda should acts like regular functions(recive "duck" and return "solid")

Prunoideae commented 3 months ago

https://github.com/Prunoideae/ProbeJS/blob/afbf8b7f7996bfc0f2b732329ffd69571a142bd5/src/main/java/moe/wolfgirl/probejs/lang/typescript/code/type/js/JSLambdaType.java#L67-L70

Use .method() before any param call to make a lambda type to type like a regular method.

Normally we expect the lambda type to be something implemented by the JS side (e.g. Consumer<Object> => (object)=> {}), so the lambda will receive concrete type and return duck type by default, so the following will work:

function testMethod(arg: (entity: $Entity) => $ItemStack$$Type){
    ...
}

testMethod(entity => {
    console.info(entity.x) // We have completions here
    return 'minecraft:apple' // and here, too
})
Prunoideae commented 3 months ago

It might be possible to make the lambda type to be aware of the context to infer correct types according to the position in the type later, but that might not be of a high priority.