grant / ts2gas

A function that transpiles TypeScript to Google Apps Script.
http://npmjs.com/ts2gas
MIT License
88 stars 11 forks source link

(WIP) Typescript 3.4 support #36

Closed PopGoesTheWza closed 5 years ago

PopGoesTheWza commented 5 years ago

Reference issue #35

Typescript 3.4 introduces new features:

package.json needs be either "typescript": "^3.4.0" or "typescript": "^3.*.*"

in test.ts the following test cases (checked if passed)

Detailed test cases input/output:

# testTypeScript_34x_highOrder
v--TS--v
// Higher order function type inference
declare function pipe<A extends any[], B, C>(ab: (...args: A) => B, bc: (b: B) => C): (...args: A) => C;

declare function list<T>(a: T): T[];
declare function box<V>(x: V): { value: V };

const listBox = pipe(list, box);  // <T>(a: T) => { value: T[] }
const boxList = pipe(box, list);  // <V>(x: V) => { value: V }[]

const x1 = listBox(42);  // { value: number[] }
const x2 = boxList('hello');  // { value: string }[]

const flip = <A, B, C>(f: (a: A, b: B) => C) => (b: B, a: A) => f(a, b);
const zip = <T, U>(x: T, y: U): [T, U] => [x, y];
const flipped = flip(zip);  // <T, U>(b: U, a: T) => [T, U]

const t1 = flipped(10, 'hello');  // [string, number]
const t2 = flipped(true, 0);  // [number, boolean]
–––
// Compiled using ts2gas 1.6.2 (TypeScript 3.4.1)
var exports = exports || {};
var module = module || { exports: exports };
var listBox = pipe(list, box); // <T>(a: T) => { value: T[] }
var boxList = pipe(box, list); // <V>(x: V) => { value: V }[]
var x1 = listBox(42); // { value: number[] }
var x2 = boxList('hello'); // { value: string }[]
var flip = function (f) { return function (b, a) { return f(a, b); }; };
var zip = function (x, y) { return [x, y]; };
var flipped = flip(zip); // <T, U>(b: U, a: T) => [T, U]
var t1 = flipped(10, 'hello'); // [string, number]
var t2 = flipped(true, 0); // [number, boolean]
 ^--GS--^
# testTypeScript_34x_improvedReadonly
v--TS--v
// Improved support for read-only arrays and tuples
function f1(mt: [number, number], rt: readonly [number, number]) {
  mt[0] = 1;  // Ok
  // rt[0] = 1;  // Error, read-only element
}

// function f2(ma: string[], ra: readonly string[], mt: [string, string], rt: readonly [string, string]) {
//   ma = ra;  // Error
//   ma = mt;  // Ok
//   ma = rt;  // Error
//   ra = ma;  // Ok
//   ra = mt;  // Ok
//   ra = rt;  // Ok
//   mt = ma;  // Error
//   mt = ra;  // Error
//   mt = rt;  // Error
//   rt = ma;  // Error
//   rt = ra;  // Error
//   rt = mt;  // Ok
// }

type ReadWrite<T> = { -readonly [P in keyof T] : T[P] };

type T0 = Readonly<string[]>;  // readonly string[]
type T1 = Readonly<[number, number]>;  // readonly [number, number]
type T2 = Partial<Readonly<string[]>>;  // readonly (string | undefined)[]
type T3 = Readonly<Partial<string[]>>;  // readonly (string | undefined)[]
type T4 = ReadWrite<Required<T3>>;  // string[]
–––
// Compiled using ts2gas 1.6.2 (TypeScript 3.4.1)
var exports = exports || {};
var module = module || { exports: exports };
// Improved support for read-only arrays and tuples
function f1(mt, rt) {
    mt[0] = 1; // Ok
    // rt[0] = 1;  // Error, read-only element
}
 ^--GS--^
# testTypeScript_34x_constContext
v--TS--v
// Const contexts for literal expressions
let x = 10 as const;  // Type 10
let y = <const> [10, 20];  // Type readonly [10, 20]
let z = { text: "hello" } as const;  // Type { readonly text: "hello" }
–––
// Compiled using ts2gas 1.6.2 (TypeScript 3.4.1)
var exports = exports || {};
var module = module || { exports: exports };
// Const contexts for literal expressions
var x = 10; // Type 10
var y = [10, 20]; // Type readonly [10, 20]
var z = { text: "hello" }; // Type { readonly text: "hello" }
 ^--GS--^
# testTypeScript_34x_globalThis
v--TS--v
// `globalThis`
// Add globalThis
// @Filename: one.ts
var a = 1;
var b = 2;
// @Filename: two.js
this.c = 3;
const total = globalThis.a + this.b + window.c + this.unknown;
–––
// Compiled using ts2gas 1.6.2 (TypeScript 3.4.1)
var exports = exports || {};
var module = module || { exports: exports };
// `globalThis`
// Add globalThis
// @Filename: one.ts
var a = 1;
var b = 2;
// @Filename: two.js
this.c = 3;
var total = globalThis.a + this.b + window.c + this.unknown;
 ^--GS--^
PopGoesTheWza commented 5 years ago

In order to fully support globalThis some polyfill or shim is likely required (though not exactly in the scope of ts2gas.

Concerning Improved support for read-only arrays and tuples a TypeScript issue already exists which I'll follow-up

PopGoesTheWza commented 5 years ago

@grant current changes are OK from my point of view.

Typescript 3.4 new features are compatible with ts2gas with the following limitations:

I let you judge as to merge or not this PR