In the discussion on #328 the consensus seems to be that people like type definitions. This moves toward generating types using jsdoc as suggested by @bollwyvl in that thread.

I don't have much Typescript experience so I would very much appreciate it if people could test them out. The types are available as CircleCI artifacts here:
https://3914-322074228-gh.circle-artifacts.com/0/root/repo/build/pyodide.d.ts

@bollwyvl said that

> types that aren't tested are probably worse than no types at all

If anyone could contribute tests, that would be very helpful (I don't know what they should look like). 

The main limitation I ran into with this approach is that Typescript supports Typescript types in jsdoc annotations but jsdoc does not. This means that if we want to automatically generate docs, we have to stick to the much more limited syntax that jsdoc supports. For example, `isPyProxy` should be typed `obj is PyProxy` but this approach does not allow that as far as I can tell. 
Some basic types. In the discussion on #328 the consensus seems to be that people like type definitions. This moves toward generating types using jsdoc as suggested by @bollwyvl in that thread.

I don't have much Typescript experience so I would very much appreciate it if people could test them out. The types are available as CircleCI artifacts here:
https://3914-322074228-gh.circle-artifacts.com/0/root/repo/build/pyodide.d.ts

@bollwyvl said that

> types that aren't tested are probably worse than no types at all

If anyone could contribute tests, that would be very helpful (I don't know what they should look like). 

The main limitation I ran into with this approach is that Typescript supports Typescript types in jsdoc annotations but jsdoc does not. This means that if we want to automatically generate docs, we have to stick to the much more limited syntax that jsdoc supports. For example, `isPyProxy` should be typed `obj is PyProxy` but this approach does not allow that as far as I can tell. 
from typing import Dict
import random

import pytest


def generate_largish_json(n_rows: int = 91746) -> Dict:
    # with n_rows = 91746, the output JSON size will be ~15 MB/10k rows

    # Note: we don't fix the random seed here, but the actual values
    # shouldn't matter
    columns = [
        ("column0", lambda: "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"),
        (
            "column1",
            lambda: random.choice(
                [
                    "notification-interval-longer",
                    "notification-interval-short",
                    "control",
                ]
            ),
        ),
        ("column2", lambda: random.choice([True, False])),
        ("column3", lambda: random.randint(0, 4)),
        ("column4", lambda: random.randint(0, 4)),
        ("column5", lambda: random.randint(0, 4)),
        ("column6", lambda: random.randint(0, 4)),
        ("column7", lambda: random.randint(0, 4)),
    ]
    data = {}
    for name, generator in columns:
        data[name] = [generator() for _ in range(n_rows)]
    return data


@pytest.mark.driver_timeout(30)
def test_pandas(selenium, request):
    selenium.load_package("pandas")
    assert len(selenium.run("import pandas\ndir(pandas)")) == 142


@pytest.mark.driver_timeout(30)
def test_extra_import(selenium, request):

    selenium.load_package("pandas")
    selenium.run("from pandas import Series, DataFrame, Panel")


@pytest.mark.driver_timeout(40)
@pytest.mark.skip_refcount_check
def test_load_largish_file(selenium_standalone, request, httpserver):
    selenium = selenium_standalone
    if selenium.browser == "chrome":
        pytest.xfail(
            "test_load_largish_file triggers a fatal runtime error in Chrome 89 see #1495"
        )

    selenium.load_package("pandas")
    selenium.load_package("matplotlib")

    n_rows = 91746

    data = generate_largish_json(n_rows)

    httpserver.expect_request("/data").respond_with_json(
        data, headers={"Access-Control-Allow-Origin": "*"}
    )
    request_url = httpserver.url_for("/data")

    selenium.run(
        f"""
        import pyodide
        import matplotlib.pyplot as plt
        import pandas as pd

        df = pd.read_json(pyodide.open_url('{request_url}'))
        assert df.shape == ({n_rows}, 8)
        """
    )

from typing import Dict
import random

import pytest


def generate_largish_json(n_rows: int = 91746) -> Dict:
    # with n_rows = 91746, the output JSON size will be ~15 MB/10k rows

    # Note: we don't fix the random seed here, but the actual values
    # shouldn't matter
    columns = [
        ("column0", lambda: "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"),
        (
            "column1",
            lambda: random.choice(
                [
                    "notification-interval-longer",
                    "notification-interval-short",
                    "control",
                ]
            ),
        ),
        ("column2", lambda: random.choice([True, False])),
        ("column3", lambda: random.randint(0, 4)),
        ("column4", lambda: random.randint(0, 4)),
        ("column5", lambda: random.randint(0, 4)),
        ("column6", lambda: random.randint(0, 4)),
        ("column7", lambda: random.randint(0, 4)),
    ]
    data = {}
    for name, generator in columns:
        data[name] = [generator() for _ in range(n_rows)]
    return data


@pytest.mark.driver_timeout(30)
def test_pandas(selenium, request):
    selenium.load_package("pandas")
    assert len(selenium.run("import pandas\ndir(pandas)")) == 142


@pytest.mark.driver_timeout(30)
def test_extra_import(selenium, request):

    selenium.load_package("pandas")
    selenium.run("from pandas import Series, DataFrame, Panel")


@pytest.mark.driver_timeout(40)
@pytest.mark.skip_refcount_check
def test_load_largish_file(selenium_standalone, request, httpserver):
    selenium = selenium_standalone
    if selenium.browser == "chrome":
        pytest.xfail(
            "test_load_largish_file triggers a fatal runtime error in Chrome 89 see #1495"
        )

    selenium.load_package("pandas")
    selenium.load_package("matplotlib")

    n_rows = 91746

    data = generate_largish_json(n_rows)

    httpserver.expect_request("/data").respond_with_json(
        data, headers={"Access-Control-Allow-Origin": "*"}
    )
    request_url = httpserver.url_for("/data")

    selenium.run(
        f"""
        import pyodide
        import matplotlib.pyplot as plt
        import pandas as pd

        df = pd.read_json(pyodide.open_url('{request_url}'))
        assert df.shape == ({n_rows}, 8)
        """
    )
