AssemblyScript / assemblyscript

A TypeScript-like language for WebAssembly.
https://www.assemblyscript.org
Apache License 2.0
16.6k stars 650 forks source link

Support type alias as syntactic sugar for class #2818

Closed a-skua closed 4 months ago

a-skua commented 4 months ago

Feature suggestion

I've understood that by defining a no constructor class, it's possible to pass object literals from JavaScript.

AS:

class Point {
  x: i32;
  y: i32;
}

export function pointToString(p: Point): string {
  return `(${p.x},${p.y})`;
}

JS:

import { pointToString } from "./build/release.js";

console.debug(pointToString({x: 1, y: 2}));

However, no constructor classes trigger syntax errors in TypeScript linters.

class Point {
  x: i32; // ERR: Property 'x' has no initializer and is not definitely assigned in the constructor.
  y: i32; // ERR: Property 'y' has no initializer and is not definitely assigned in the constructor.
}

Therefore, I'm considering whether it's feasible to use type aliases as syntactic sugar for no constructor classes.

type Point = {
  x: i32;
  y: i32;
};

export function pointToString(p: Point): string {
  return `(${p.x},${p.y})`;
}

This type Point is treated as class Point in AssemblyScript, so the output of asbuild will be the same code. I think for TypeScript users, object type aliases might be more familiar.

Feature suggestion

We will permit the following syntax as syntactic sugar for classes.

type Point = {
  x: i32;
  y: i32;
};
/*
// Same code:
class Point {
  x: i32;
  y: i32;
};
*/

e.g. https://github.com/a-skua/assemblyscript/commit/d9d5e4e49188fcaedf82350fa196856d435cb7fd

MaxGraey commented 4 months ago

You can use ! to bypass linter:

class Point {
  x!: i32;
  y!: i32;
}

or

class Point {
  x: i32 = 0;
  y: i32 = 0;
}
a-skua commented 4 months ago

@MaxGraey Thanks for the info! However, it seems that ! is not currently supported in AS.

PEDANTIC AS906: Unnecessary definite assignment.
    :
 19 │ x!: i32;
    │ ~
    └─ in assembly/index.ts(19,3)

PEDANTIC AS906: Unnecessary definite assignment.
    :
 20 │ y!: i32;
    │ ~
    └─ in assembly/index.ts(20,3)

Therefore, it would be written like this.

class Point {
  x: i32 = 0;
  y: i32 = 0;
}

But what I want to do here is not initializing with zero, but defining a type. I understand that AS is like TS but is a different language. How closely do you intend to mimic TS syntax?

https://www.assemblyscript.org/compiler.html#host-bindings

Type Strategy Description
Object Copy If a plain object. That is: Has no constructor or non-public fields.
Object By reference If not a plain object. Passed as an opaque reference counted pointer.

This proposal arose from the observation that "no constructor" classes are treated differently than regular classes, prompting the question of whether we could adopt a writing style closer to TS.

I'm now thinking that supporting ! instead of type aliases would also be acceptable.

class Point {
  x!: i32;
  y!: i32;
}
CountBleck commented 4 months ago

That's PEDANTIC. You can safely ignore that.

a-skua commented 4 months ago

I see, I misunderstood PEDANTIC as a build failure. It's already supported. The issue is resolved, so I'll close this. Thank you for your help!