johnfn / ts2gd

💥 Compile TypeScript to GDScript for Godot
200 stars 14 forks source link

utility function import #66

Open ksjogo opened 2 years ago

ksjogo commented 2 years ago

Given a file util.ts with

export function map() {
  return 1;
}

and a file Actors.ts with

import { map } from "./util";

export default class Actor {
  something() {
    return map();
  }
}

The generated util.gd file will be empty and only have the comment:

# This file has been autogenerated by ts2gd. DO NOT EDIT!

The Actor.gd file will look like:


# This file has been autogenerated by ts2gd. DO NOT EDIT!

class_name Actor

var () => number = load("res://actors/util.gd")

func something():
  return map()
adamuso commented 2 years ago

To clarify, this issue is related to #61 right? Because before that export default was never a thing in ts2gd :)

ksjogo commented 2 years ago

Ahh, yeah I tested it on that branch first, put it also happens on main (without the default).

adamuso commented 2 years ago

I think in this case ts2gd should just show an error because in GDScript you cannot create a helper function without creating a class. The only option is to use static function in GDScript like in code below, but currently for some reason static in ts2gd is not supported (I think we should add support for it, added issue #69).

# A.gd

static func utilFunc():
  print("util")
# B.gd

extends Node

const A = preload("res://A.gd")

static func _ready():
  A.utilFunc()
johnfn commented 2 years ago

This is obviously an error today so we should probably emit an error for now, rather than just incorrect code. :)

But I disagree that this should be an error for all time. It's a very convenient pattern in TS to export and import top-level functions and variables, so if we can make it work somehow, I think we should try to.

One idea I had for this case was to gather up all top-level declarations into a new class and make that class an autoload. e.g.

util.ts:

export function map() {
  return 1;
}

generates UtilAutoload.gd

class_name
UtilAutoload

func map():
    return 1

Then map() would emit UtilAutoload.map()

I know this kinda goes against the principle of 'simplest possible emit' but it is such a handy thing to do in TS that I wouldn't want to disallow people from doing it.