Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -470,6 +470,10 @@ jobs:
run: make
working-directory: ./test/javascript_prelude

- name: Test generated TypeScript declarations
run: make test
working-directory: ./test/typescript_declarations

- name: Test export of hex tarball
run: make test
working-directory: ./test/hextarball
Expand Down
5 changes: 5 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ test: ## Run the compiler unit tests
cd test/project_javascript && cargo run clean && cargo run check && cargo run test
cd test/project_deno && cargo run clean && cargo run check && cargo run test
cd test/hextarball && make test
cd test/typescript_declarations && make test
cd test/running_modules && make test
cd test/subdir_ffi && make

Expand Down Expand Up @@ -51,6 +52,10 @@ test-watch: ## Run compiler tests when files change
export-hex-tarball-test: ## Run `gleam export hex-tarball` and verify it is created
cd test/hextarball && make test

.PHONY: typescript-declarations-test
typescript-declarations-test: ## Check that generated TypeScript declaration compile
cd test/typescript_declarations && make test

.PHONY: benchmark
benchmark: ## Run the benchmarks
cd benchmark/list && make
Expand Down
4 changes: 4 additions & 0 deletions test/typescript_declarations/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
*.beam
*.ez
/build
erl_crash.dump
8 changes: 8 additions & 0 deletions test/typescript_declarations/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
.PHONY: clean
clean:
rm -rf build

.PHONY: test
test:
cargo run --quiet -- build
tsc ./main.ts --strict --noEmit --lib es2015,dom
3 changes: 3 additions & 0 deletions test/typescript_declarations/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# typescript_declarations

Check that generated TypeScript declarartions are correct. This requires `tsc` installed and be in PATH.
9 changes: 9 additions & 0 deletions test/typescript_declarations/gleam.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
name = "typescript_declarations"
version = "1.0.0"
target = "javascript"

[javascript]
typescript_declarations = true

[dependencies]
gleam_stdlib = ">= 0.44.0 and < 2.0.0"
79 changes: 79 additions & 0 deletions test/typescript_declarations/main.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import type { Option$ } from "./build/dev/javascript/gleam_stdlib/gleam/option.d.mts";
import { List, Ok, Result } from "./build/dev/javascript/typescript_declarations/gleam.mjs";
import * as Gleam from "./build/dev/javascript/typescript_declarations/typescript_declarations.mjs"

// Check add and add_alias
const sum: number = Gleam.add_alias(Gleam.add(1, 2), 908);

// Check ID lists constants
const count_of_moderators: number = Gleam.moders.countLength();
const count_of_administrators: number = Gleam.admins.countLength();

// Check add_one closure
const add_one: (_: number) => number = Gleam.add_one()
const two: number = add_one(1)

// Check UserId type alias
const first_moderator: Gleam.UserId = Gleam.moders.toArray()[ 0];
const first_moderator_num: number = first_moderator;
const me: UserID = 84738;
type UserID = Gleam.UserId;

// Check is_divisible_by
const is_five_divisible_by_two: boolean = Gleam.is_divisible_by(5, 2);

// Check extern alert function if we are in browser target
if (typeof window != undefined) {
Gleam.js_alert("Hello!");
}

// Check generic twice function
const twice_number: number = Gleam.twice(45, add_one);

// Check recursive sum_list
const sum_of_list: number = Gleam.sum_list(List.fromArray([10, 25, 65383, 8910, 1893]), 0);

// Check results
const result_ok: Result<number, number> = new Ok(10);
const is_ok: boolean = Gleam.is_ok_result(result_ok);

// Check name_description tuple
const name: string = Gleam.name_description[0];
const description: string = Gleam.name_description[1];

// Check User and related functions
const user: Gleam.User$ = new Gleam.User("King", 83874, new Gleam.PlainUser());
const guest: Gleam.User$ = new Gleam.Guest();
const user_username: Option$<string> = Gleam.user_name(user);
const guest_username: Option$<string> = Gleam.user_name(guest);
const plain_user_string: string = Gleam.role_string((user as Gleam.User).role);

// Check Either type
const left_either: Gleam.Either$<string, number> = new Gleam.Left("Hello!");
const right_either: Gleam.Either$<string, number> = new Gleam.Right(3747);

// This added since TypeScript will give warnings about unused things otherwise
void [
sum,
count_of_administrators,
count_of_moderators,
add_one,
two,
first_moderator,
first_moderator_num,
me,
is_five_divisible_by_two,
twice_number,
sum_of_list,
result_ok,
is_ok,
name,
description,
user,
guest,
user_username,
guest_username,
plain_user_string,
left_either,
right_either,
]
9 changes: 9 additions & 0 deletions test/typescript_declarations/manifest.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# This file was generated by Gleam
# You typically do not need to edit this file

packages = [
{ name = "gleam_stdlib", version = "0.62.1", build_tools = ["gleam"], requirements = [], otp_app = "gleam_stdlib", source = "hex", outer_checksum = "0080706D3A5A9A36C40C68481D1D231D243AF602E6D2A2BE67BA8F8F4DFF45EC" },
]

[requirements]
gleam_stdlib = { version = ">= 0.44.0 and < 2.0.0" }
102 changes: 102 additions & 0 deletions test/typescript_declarations/src/typescript_declarations.gleam
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
import gleam/option.{type Option}
import gleam/result

/// Greeting for user
pub const greeting: String = "Hello, dear user!"

/// Add two numbers
pub fn add(first a: Int, second b: Int) -> Int {
a + b
}

/// Returns true if number is divisible by another
pub fn is_divisible_by(number num: Int, divider div: Int) -> Bool {
case num % div {
0 -> True
_ -> False
}
}

/// ID of specific user
pub type UserId =
Int

/// Alias to add function
pub const add_alias = add

/// Return function that will add one to given number
pub fn add_one() -> fn(Int) -> Int {
let func = add(1, _)
func
}

/// IDs of administrators
pub const admins: List(UserId) = [00_010, 00_000, 00_001, 00_002, 29_373]

/// IDs of moderators
pub const moders = [01_013, 36_371, 74_839, 18_930, 36_373]

/// Create alert on browser target
@external(javascript, "globalThis", "alert")
pub fn js_alert(text: String) -> Nil

/// Twice value via given function
pub fn twice(val: a, function: fn(a) -> a) -> a {
function(function(val))
}

/// Recursively sum list of numbers
pub fn sum_list(list: List(Int), total: Int) -> Int {
case list {
[first, ..rest] -> sum_list(rest, total + first)
[] -> total
}
}

/// Returns true if result is ok
pub fn is_ok_result(res: Result(a, b)) -> Bool {
result.is_ok(res)
}

/// First value is name and second is description
pub const name_description = #("MyApp", "My Awesome Application")

/// Role of user
pub type UserRole {
/// Administrator
Administrator
/// Moderator
Moderator
/// Just a user
PlainUser
}

/// Represents user
pub type User {
/// Represents registered user
User(username: String, id: UserId, role: UserRole)
/// Represents guest without any data
Guest
}

/// Get name of user, None if user is guest
pub fn user_name(user: User) -> Option(String) {
case user {
User(name, ..) -> option.Some(name)
Guest -> option.None
}
}

/// Format user role as string
pub fn role_string(role: UserRole) -> String {
case role {
PlainUser -> "user"
Moderator -> "moderator"
Administrator -> "admin"
}
}

pub type Either(a, b) {
Left(a)
Right(b)
}
Loading